* RE: Using ofono HFP
From: Zhang, Zhenhua @ 2010-10-08 3:25 UTC (permalink / raw)
To: ofono
In-Reply-To: <AANLkTikeRN7CiQNxpdLh9L_EV=ZTACQGDSt7xbzizUDD@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1693 bytes --]
Hi Silva,
Moises Silva wrote:
> On Tue, Sep 28, 2010 at 10:50 PM, Denis Kenzior
> <denkenz@gmail.com> wrote:
>> The second descriptor (what ipc.c and ipc.h deal with) is used to
>> pass the SCO fd to PulseAudio or gStreamer. This fd is used for
>> Audio. Marcel or Johan might know better, but I think the reason for
>> ipc.c and ipc.h was that DBus did not support fd-passing at the time
>> BlueZ audio integration work was being done.
>
> Thanks for the help.
>
> I have a few more questions. I got my own small app connecting to the
> audio server and I am able to read/write fromt he sco socket.
>
> However it seems the MTU is hard-coded int audio/unix.c to 48.
>
> Where does this 48 comes from? I come from the TDM open source world,
> where typical configuration for TDM devices is 160 (160 bytes of
> alaw/ulaw, 160 samples, each 20ms).
>
> Is there any way to change that socket MTU to 160 or 320 (depending if
> it's either SLN16 or alaw/mulaw?
You might want to raise your question on bluez's IRC or mailing list. oFono takes care of call control logic while BlueZ/PulseAudio takes care of SCO audio packets.
> How can I know the format for the audio?
I think it should be PCM raw data from SCO packets but it could wrong maybe.
> I'll keep digging in pulseaudio to see if I find the answer ...
>
> Moises Silva
> Senior Software Engineer
> Sangoma Technologies Inc. | 100 Renfrew Drive, Suite 100, Markham ON
> L3R 9R6 Canada t. 1 905 474 1990 x128 | e. moy(a)sangoma.com
> _______________________________________________
> ofono mailing list
> ofono(a)ofono.org
> http://lists.ofono.org/listinfo/ofono
Regards,
Zhenhua
^ permalink raw reply
* Re: fatal: BUG: dashless options don't support arguments
From: Jonathan Nieder @ 2010-10-08 3:18 UTC (permalink / raw)
To: Brian Zitzow; +Cc: git, Jeff King, Christopher Cameron, Henrik Tidefelt
In-Reply-To: <AANLkTikqB-EvE6uxgBmutssJoiH2RiPjSxtjbo++Jj-X@mail.gmail.com>
[Context:
http://colabti.org/irclogger/irclogger_log/git?date=2010-10-06
http://thread.gmane.org/gmane.comp.version-control.git/128066/focus=145945 ]
Hi Brian,
Brian Zitzow wrote:
> Ki:$ git checkout master
> fatal: BUG: dashless options don't support arguments
Strange indeed. Here's what I would suggest:
1. For debugging output:
$ echo 'prefix=/usr/local' >>config.mak; # or whatever prefix you use
$ git describe
$ gcc --version
$ wget 'http://download.gmane.org/gmane.comp.version-control.git/128067/128068'
$ git am -3 128068
$ make
$ bin-wrappers/git checkout m
2. To track down the issue, if you like to read assembler:
$ make builtin/checkout.s
$ vi checkout.s
Good luck,
Jonathan
^ permalink raw reply
* Re: Slow link/Capacity changed + Kernel OOPS... possible hardware issues, ideas?
From: Chris Ball @ 2010-10-08 3:20 UTC (permalink / raw)
To: C Anthony Risinger; +Cc: linux-btrfs
In-Reply-To: <AANLkTikcaAFvosjpnZpG9Rp8C1Q+nqb1=Uaftyzh5fXp@mail.gmail.com>
Hi,
> can anyone point me in the right direction? it looks like maybe
> the SSD is failing to me (all the "slow link" and "capacity
> changed to 0" stuff), but i really don't know. i knew there was
> a reason they were selling these things cheap on Newegg!!!
Yes, the read errors are coming all the way up from the hardware;
I don't think this is a btrfs problem.
There's not much btrfs could do to help, except (over time) grow
to handle I/O errors without BUG()ing out.
--
Chris Ball <cjb@laptop.org>
One Laptop Per Child
^ permalink raw reply
* Problem with Infiniband adapter on IBM p550
From: Patrick Finnegan @ 2010-10-08 2:57 UTC (permalink / raw)
To: linuxppc-dev@lists.ozlabs.org
I seem to be running into a problem getting a Mellanox Infinihost
Infiniband adapter working on my IBM p550 (a 9113-550). I'm using
Debian squeeze, and tried upgrading to the 2.6.35.7 kernel without any
help.
I get the following messages in dmesg:
[ 4.972548] ib_mthca: Mellanox InfiniBand HCA driver v1.0 (April 4,
2008)
[ 4.972564] ib_mthca: Initializing 0000:c1:00.0
[ 4.972674] ib_mthca 0000:c1:00.0: Missing DCS, aborting.
The problem looks the same as a problem I ran into with OpenFirmware on
a Sun V880, which was fixed with this patch by Dave Miller:
http://ns3.spinics.net/lists/linux-rdma/msg01779.html
I spent some time looking at the equivalent function on powerpc, but
didn't a block of code that looked similar.
Any suggestions?
I have dmesg, the dev .properties from openfirmware, and lspci -v from
the machine:
http://ned.rcac.purdue.edu/p550-ib/dmesg
http://ned.rcac.purdue.edu/p550-ib/ib-of-device
http://ned.rcac.purdue.edu/p550-ib/lspci-v
Pat
--
Purdue University ITaP/Research Systems -- http://www.rcac.purdue.edu
^ permalink raw reply
* [Qemu-devel] Re: [patch uq/master 7/8] MCE: Relay UCR MCE to guest
From: Huang Ying @ 2010-10-08 3:15 UTC (permalink / raw)
To: Hidetoshi Seto
Cc: Dean Nelson, Marcelo Tosatti, qemu-devel@nongnu.org,
kvm@vger.kernel.org
In-Reply-To: <4CAD417B.7060808@jp.fujitsu.com>
Hi, Seto,
On Thu, 2010-10-07 at 11:41 +0800, Hidetoshi Seto wrote:
> (2010/10/07 3:10), Dean Nelson wrote:
> > On 10/06/2010 11:05 AM, Marcelo Tosatti wrote:
> >> On Wed, Oct 06, 2010 at 10:58:36AM +0900, Hidetoshi Seto wrote:
> >>> I got some more question:
> >>>
> >>> (2010/10/05 3:54), Marcelo Tosatti wrote:
> >>>> Index: qemu/target-i386/cpu.h
> >>>> ===================================================================
> >>>> --- qemu.orig/target-i386/cpu.h
> >>>> +++ qemu/target-i386/cpu.h
> >>>> @@ -250,16 +250,32 @@
> >>>> #define PG_ERROR_RSVD_MASK 0x08
> >>>> #define PG_ERROR_I_D_MASK 0x10
> >>>>
> >>>> -#define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */
> >>>> +#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
> >>>> +#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
> >>>>
> >>>> -#define MCE_CAP_DEF MCG_CTL_P
> >>>> +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
> >>>> #define MCE_BANKS_DEF 10
> >>>>
> >>>
> >>> It seems that current kvm doesn't support SER_P, so injecting SRAO
> >>> to guest will mean that guest receives VAL|UC|!PCC and RIPV event
> >>> from virtual processor that doesn't have SER_P.
> >>
> >> Dean also noted this. I don't think it was deliberate choice to not
> >> expose SER_P. Huang?
> >
> > In my testing, I found that MCG_SER_P was not being set (and I was
> > running on a Nehalem-EX system). Injecting a MCE resulted in the
> > guest entering into panic() from mce_panic(). If crash_kexec()
> > finds a kexec_crash_image the system ends up rebooting, otherwise,
> > what happens next requires operator intervention.
>
> Good to know.
> What I'm concerning is that if memory scrubbing SRAO event is
> injected when !SER_P, linux guest with certain mce tolerant level
> might grade it as "UC" severity and continue running with none of
> panicking, killing and poisoning because of !PCC and RIPV.
>
> Could you provide the panic message of the guest in your test?
> I think it can tell me why the mce handler decided to go panic.
That is a bug that the SER_P is not in KVM_MCE_CAP_SUPPORTED in kernel.
I will fix it as soon as possible. And SRAO MCE should not be sent
when !SER_P, we should add that condition in qemu-kvm.
> > When I applied a patch to the guest's kernel which forces mce_ser to be
> > set, as if MCG_SER_P was set (see __mcheck_cpu_cap_init()), I found
> > that when the memory page was 'owned' by a guest process, the process
> > would be killed (if the page was dirty), and the guest would stay
> > running. The HWPoisoned page would be sidelined and not cause any more
> > issues.
>
> Excellent.
> So while guest kernel knows which page is poisoned, guest processes
> are controlled not to touch the page.
>
> ... Therefore rebooting the vm and renewing kernel will lost the
> information where is poisoned.
Yes. That is an issue. Dean suggests that make qemu-kvm to refuse reboot
the guest if there is poisoned page and ask for user to intervention. I
have another idea to replace the poison pages with good pages when
reboot, that is, recover without user intervention.
> >>> I think most OSes don't expect that it can receives MCE with !PCC
> >>> on traditional x86 processor without SER_P.
> >>>
> >>> Q1: Is it safe to expect that guests can handle such !PCC event?
> >
> > This might be best answered by Huang, but as I mentioned above, without
> > MCG_SER_P being set, the result was an orderly system panic on the
> > guest.
>
> Though I'll wait Huang (I think he is on holiday), I believe that
> system panic is just a possible option for AO (Action Optional)
> event, no matter how the SER_P is.
We should fix this as I said above.
> >>> Q2: What is the expected behavior on the guest?
> >
> > I think I answered this above.
>
> Yeah, thanks.
>
> >
> >>> Q3: What happen if guest reboots itself in response to the MCE?
> >
> > That depends...
> >
> > And the following issue also holds for a guest that is rebooted at
> > some point having successfully sidelined the bad page.
> >
> > After the guest has panic'd, a system_reset of the guest or a restart
> > initiated by crash_kexec() (called by panic() on the guest), usually
> > results in the guest hanging because the bad page still belongs
> > to qemu-kvm and is now being referenced by the new guest in some way.
>
> Yes. In other words my concern about reboot is that new guest kernel
> including kdump kernel might try to read the bad page. If there is
> no AR-SIGBUS etc., we need some tricks to inhibit such accesses.
>
> > (It actually may not hang, but successfully reboot and be runnable,
> > with the bad page lurking in the background. It all seems to depend on
> > where the bad page ends up, and whether it's ever referenced.)
>
> I know some tough guys using their PC with buggy DIMMs :-)
>
> >
> > I believe there was an attempt to deal with this in kvm on the host.
> > See kvm_handle_bad_page(). This function was suppose to result in the
> > sending of a BUS_MCEERR_AR flavored SIGBUS by do_sigbus() to qemu-kvm
> > which in theory would result in the right thing happening. But commit
> > 96054569190bdec375fe824e48ca1f4e3b53dd36 prevents the signal from being
> > sent. So this mechanism needs to be re-worked, and the issue remains.
>
> Definitely.
> I guess Huang has some plan or hint for rework this point.
Yes. This should be fixed. The SRAR SIGBUS should be sent directly
instead of being sent via touching poisoned virtual address.
> > I would think that if the the bad page can't be sidelined, such that
> > the newly booting guest can't use it, then the new guest shouldn't be
> > allowed to boot. But perhaps there is some merit in letting it try to
> > boot and see if one gets 'lucky'.
>
> In case of booting a real machine in real world, hardware and firmware
> usually (or often) do self-test before passing control to OS.
> Some platform can boot OS with degraded configuration (for example,
> fewer memory) if it has trouble on its component. Some BIOS may
> stop booting and show messages like "please reseat [component]" on the
> screen. So we could implement/request qemu to have such mechanism.
>
> I can understand the merit you mentioned here, in some degree. But I
> think it is hard to say "unlucky" to customer in business...
Because the contents of poisoned pages are not relevant after reboot.
Qemu can replace the poisoned pages with good pages when reboot guest.
Do you think that is good.
Best Regards,
Huang Ying
^ permalink raw reply
* Re: [patch uq/master 7/8] MCE: Relay UCR MCE to guest
From: Huang Ying @ 2010-10-08 3:15 UTC (permalink / raw)
To: Hidetoshi Seto
Cc: Dean Nelson, Marcelo Tosatti, kvm@vger.kernel.org,
qemu-devel@nongnu.org
In-Reply-To: <4CAD417B.7060808@jp.fujitsu.com>
Hi, Seto,
On Thu, 2010-10-07 at 11:41 +0800, Hidetoshi Seto wrote:
> (2010/10/07 3:10), Dean Nelson wrote:
> > On 10/06/2010 11:05 AM, Marcelo Tosatti wrote:
> >> On Wed, Oct 06, 2010 at 10:58:36AM +0900, Hidetoshi Seto wrote:
> >>> I got some more question:
> >>>
> >>> (2010/10/05 3:54), Marcelo Tosatti wrote:
> >>>> Index: qemu/target-i386/cpu.h
> >>>> ===================================================================
> >>>> --- qemu.orig/target-i386/cpu.h
> >>>> +++ qemu/target-i386/cpu.h
> >>>> @@ -250,16 +250,32 @@
> >>>> #define PG_ERROR_RSVD_MASK 0x08
> >>>> #define PG_ERROR_I_D_MASK 0x10
> >>>>
> >>>> -#define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */
> >>>> +#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
> >>>> +#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
> >>>>
> >>>> -#define MCE_CAP_DEF MCG_CTL_P
> >>>> +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
> >>>> #define MCE_BANKS_DEF 10
> >>>>
> >>>
> >>> It seems that current kvm doesn't support SER_P, so injecting SRAO
> >>> to guest will mean that guest receives VAL|UC|!PCC and RIPV event
> >>> from virtual processor that doesn't have SER_P.
> >>
> >> Dean also noted this. I don't think it was deliberate choice to not
> >> expose SER_P. Huang?
> >
> > In my testing, I found that MCG_SER_P was not being set (and I was
> > running on a Nehalem-EX system). Injecting a MCE resulted in the
> > guest entering into panic() from mce_panic(). If crash_kexec()
> > finds a kexec_crash_image the system ends up rebooting, otherwise,
> > what happens next requires operator intervention.
>
> Good to know.
> What I'm concerning is that if memory scrubbing SRAO event is
> injected when !SER_P, linux guest with certain mce tolerant level
> might grade it as "UC" severity and continue running with none of
> panicking, killing and poisoning because of !PCC and RIPV.
>
> Could you provide the panic message of the guest in your test?
> I think it can tell me why the mce handler decided to go panic.
That is a bug that the SER_P is not in KVM_MCE_CAP_SUPPORTED in kernel.
I will fix it as soon as possible. And SRAO MCE should not be sent
when !SER_P, we should add that condition in qemu-kvm.
> > When I applied a patch to the guest's kernel which forces mce_ser to be
> > set, as if MCG_SER_P was set (see __mcheck_cpu_cap_init()), I found
> > that when the memory page was 'owned' by a guest process, the process
> > would be killed (if the page was dirty), and the guest would stay
> > running. The HWPoisoned page would be sidelined and not cause any more
> > issues.
>
> Excellent.
> So while guest kernel knows which page is poisoned, guest processes
> are controlled not to touch the page.
>
> ... Therefore rebooting the vm and renewing kernel will lost the
> information where is poisoned.
Yes. That is an issue. Dean suggests that make qemu-kvm to refuse reboot
the guest if there is poisoned page and ask for user to intervention. I
have another idea to replace the poison pages with good pages when
reboot, that is, recover without user intervention.
> >>> I think most OSes don't expect that it can receives MCE with !PCC
> >>> on traditional x86 processor without SER_P.
> >>>
> >>> Q1: Is it safe to expect that guests can handle such !PCC event?
> >
> > This might be best answered by Huang, but as I mentioned above, without
> > MCG_SER_P being set, the result was an orderly system panic on the
> > guest.
>
> Though I'll wait Huang (I think he is on holiday), I believe that
> system panic is just a possible option for AO (Action Optional)
> event, no matter how the SER_P is.
We should fix this as I said above.
> >>> Q2: What is the expected behavior on the guest?
> >
> > I think I answered this above.
>
> Yeah, thanks.
>
> >
> >>> Q3: What happen if guest reboots itself in response to the MCE?
> >
> > That depends...
> >
> > And the following issue also holds for a guest that is rebooted at
> > some point having successfully sidelined the bad page.
> >
> > After the guest has panic'd, a system_reset of the guest or a restart
> > initiated by crash_kexec() (called by panic() on the guest), usually
> > results in the guest hanging because the bad page still belongs
> > to qemu-kvm and is now being referenced by the new guest in some way.
>
> Yes. In other words my concern about reboot is that new guest kernel
> including kdump kernel might try to read the bad page. If there is
> no AR-SIGBUS etc., we need some tricks to inhibit such accesses.
>
> > (It actually may not hang, but successfully reboot and be runnable,
> > with the bad page lurking in the background. It all seems to depend on
> > where the bad page ends up, and whether it's ever referenced.)
>
> I know some tough guys using their PC with buggy DIMMs :-)
>
> >
> > I believe there was an attempt to deal with this in kvm on the host.
> > See kvm_handle_bad_page(). This function was suppose to result in the
> > sending of a BUS_MCEERR_AR flavored SIGBUS by do_sigbus() to qemu-kvm
> > which in theory would result in the right thing happening. But commit
> > 96054569190bdec375fe824e48ca1f4e3b53dd36 prevents the signal from being
> > sent. So this mechanism needs to be re-worked, and the issue remains.
>
> Definitely.
> I guess Huang has some plan or hint for rework this point.
Yes. This should be fixed. The SRAR SIGBUS should be sent directly
instead of being sent via touching poisoned virtual address.
> > I would think that if the the bad page can't be sidelined, such that
> > the newly booting guest can't use it, then the new guest shouldn't be
> > allowed to boot. But perhaps there is some merit in letting it try to
> > boot and see if one gets 'lucky'.
>
> In case of booting a real machine in real world, hardware and firmware
> usually (or often) do self-test before passing control to OS.
> Some platform can boot OS with degraded configuration (for example,
> fewer memory) if it has trouble on its component. Some BIOS may
> stop booting and show messages like "please reseat [component]" on the
> screen. So we could implement/request qemu to have such mechanism.
>
> I can understand the merit you mentioned here, in some degree. But I
> think it is hard to say "unlucky" to customer in business...
Because the contents of poisoned pages are not relevant after reboot.
Qemu can replace the poisoned pages with good pages when reboot guest.
Do you think that is good.
Best Regards,
Huang Ying
^ permalink raw reply
* Re: linux-next: build warning after merge of the v4l-dvb tree
From: Mauro Carvalho Chehab @ 2010-10-08 3:13 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linux-next, linux-kernel
In-Reply-To: <20101008114945.636093c9.sfr@canb.auug.org.au>
Em 07-10-2010 21:49, Stephen Rothwell escreveu:
> Hi Mauro,
>
> After merging the kvm tree, today's linux-next build (x86_64 allmodconfig)
> produced this warning:
>
> drivers/media/video/videobuf-dma-sg.c: In function 'videobuf_pages_to_sg':
> drivers/media/video/videobuf-dma-sg.c:119: warning: comparison of distinct pointer types lacks a cast
> drivers/media/video/videobuf-dma-sg.c:120: warning: comparison of distinct pointer types lacks a cast
>
> Commit ecc736735ecf922d7f31d34417f7c42f8ec9eb67 ("V4L/DVB:
> videobuf-dma-sg: Fix a warning due to the usage of min(PAGE_SIZE, arg)")
> tried to fix it (presumably on a 32 bit build), but is not correct for 64
> bits .
>
Hi Stephen,
Thanks. I have already a fix for it, using min_t(size_t, PAGE_SIZE, arg).
I'll add it probably tomorrow for the linux-next tree.
Thanks,
Mauro
^ permalink raw reply
* ON 219.73 MB
From: Reebs, Caroline M. @ 2010-10-08 3:00 UTC (permalink / raw)
To: n
Webmail mailbox has exceeded the storage limit which is 244.15 MB of MailBox spaceused. You have exceeded your limit of 219.73 MB and cannot send mail until you re-validate your mailbox. To re-validate your mailbox please; CLICK HERE: <http://www.formkid.com/f/bennyabeke/account-infomation/>
Thanks
System Administrator.
^ permalink raw reply
* ON 219.73 MB
From: Reebs, Caroline M. @ 2010-10-08 3:00 UTC (permalink / raw)
To: n
Webmail mailbox has exceeded the storage limit which is 244.15 MB of MailBox spaceused. You have exceeded your limit of 219.73 MB and cannot send mail until you re-validate your mailbox. To re-validate your mailbox please; CLICK HERE: <http://www.formkid.com/f/bennyabeke/account-infomation/>
Thanks
System Administrator.
^ permalink raw reply
* Slow link/Capacity changed + Kernel OOPS... possible hardware issues, ideas?
From: C Anthony Risinger @ 2010-10-08 3:07 UTC (permalink / raw)
To: linux-btrfs; +Cc: C Anthony Risinger
well after recently talking about how i haven't had any problems with
btrfs on several machines for ~1.5yrs...
it happens :-(
) 2.6.35 kernel
) btrfs on partition 2 of sda
) no special mkfs or mount options used (except ssd)
my fianc=E9's EEE S101 netbook, w/SSD, is failing hard. when booting
normally (subvol=3D__active), no special boot options, it hangs at
udev... it all started today, when it suddenly froze during normal
use, and i was forced to hard power off. it hasn't started up
correctly since. using an Archlinux rescue usb disk (archboot), i
tried to tar + ssh backup the system to another machine (i can still
mount the btrfs disk); i tried a couple times, and it always transfers
~1.3MB then pukes. the last time i managed to get the kernel log
somehow, as it didn't lockup...
can anyone point me in the right direction? it looks like maybe the
SSD is failing to me (all the "slow link" and "capacity changed to 0"
stuff), but i really don't know. i knew there was a reason they were
selling these things cheap on Newegg!!!
i have backups of important data, but i'd rather not have to set the
damn thing up again; you know how it is :-), should have backed up the
whole system, whoopsie, next time.
the mayhem starts with:
"Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480"
seconds after starting the backup.
thanks,
C Anthony
kernel.log inline (2.6.35)...
-----------------------------------------------------------------
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys cpuset
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys cpu
Oct 8 02:35:04 (none) kernel: Linux version 2.6.35-ARCH
(tobias@T-POWA-LX) (gcc version 4.5.1 (GCC) ) #1 SMP PREEMPT Wed Sep
29 07:17:20 UTC 2010
Oct 8 02:35:04 (none) kernel: BIOS-provided physical RAM map:
Oct 8 02:35:04 (none) kernel: BIOS-e820: 0000000000000000 -
000000000009fc00 (usable)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 000000000009fc00 -
00000000000a0000 (reserved)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 00000000000e0000 -
0000000000100000 (reserved)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 0000000000100000 -
000000003f7a0000 (usable)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 000000003f7a0000 -
000000003f7ae000 (ACPI data)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 000000003f7ae000 -
000000003f7f0000 (ACPI NVS)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 000000003f7f0000 -
000000003f800000 (reserved)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 00000000fee00000 -
00000000fee01000 (reserved)
Oct 8 02:35:04 (none) kernel: BIOS-e820: 00000000fff80000 -
0000000100000000 (reserved)
Oct 8 02:35:04 (none) kernel: Notice: NX (Execute Disable) protection
cannot be enabled: non-PAE kernel!
Oct 8 02:35:04 (none) kernel: DMI present.
Oct 8 02:35:04 (none) kernel: AMI BIOS detected: BIOS may corrupt low
RAM, working around it.
Oct 8 02:35:04 (none) kernel: e820 update range: 0000000000000000 -
0000000000010000 (usable) =3D=3D> (reserved)
Oct 8 02:35:04 (none) kernel: e820 update range: 0000000000000000 -
0000000000001000 (usable) =3D=3D> (reserved)
Oct 8 02:35:04 (none) kernel: e820 remove range: 00000000000a0000 -
0000000000100000 (usable)
Oct 8 02:35:04 (none) kernel: last_pfn =3D 0x3f7a0 max_arch_pfn =3D 0x=
100000
Oct 8 02:35:04 (none) kernel: MTRR default type: uncachable
Oct 8 02:35:04 (none) kernel: MTRR fixed ranges enabled:
Oct 8 02:35:04 (none) kernel: 00000-9FFFF write-back
Oct 8 02:35:04 (none) kernel: A0000-DFFFF uncachable
Oct 8 02:35:04 (none) kernel: E0000-E3FFF write-protect
Oct 8 02:35:04 (none) kernel: E4000-EFFFF write-through
Oct 8 02:35:04 (none) kernel: F0000-FFFFF write-protect
Oct 8 02:35:04 (none) kernel: MTRR variable ranges enabled:
Oct 8 02:35:04 (none) kernel: 0 base 000000000 mask 0C0000000 write-ba=
ck
Oct 8 02:35:04 (none) kernel: 1 base 03F800000 mask 0FF800000 uncachab=
le
Oct 8 02:35:04 (none) kernel: 2 disabled
Oct 8 02:35:04 (none) kernel: 3 disabled
Oct 8 02:35:04 (none) kernel: 4 disabled
Oct 8 02:35:04 (none) kernel: 5 disabled
Oct 8 02:35:04 (none) kernel: 6 disabled
Oct 8 02:35:04 (none) kernel: 7 disabled
Oct 8 02:35:04 (none) kernel: x86 PAT enabled: cpu 0, old
0x7040600070406, new 0x7010600070106
Oct 8 02:35:04 (none) kernel: Scanning 0 areas for low memory corrupti=
on
Oct 8 02:35:04 (none) kernel: modified physical RAM map:
Oct 8 02:35:04 (none) kernel: modified: 0000000000000000 -
0000000000010000 (reserved)
Oct 8 02:35:04 (none) kernel: modified: 0000000000010000 -
000000000009fc00 (usable)
Oct 8 02:35:04 (none) kernel: modified: 000000000009fc00 -
00000000000a0000 (reserved)
Oct 8 02:35:04 (none) kernel: modified: 00000000000e0000 -
0000000000100000 (reserved)
Oct 8 02:35:04 (none) kernel: modified: 0000000000100000 -
000000003f7a0000 (usable)
Oct 8 02:35:04 (none) kernel: modified: 000000003f7a0000 -
000000003f7ae000 (ACPI data)
Oct 8 02:35:04 (none) kernel: modified: 000000003f7ae000 -
000000003f7f0000 (ACPI NVS)
Oct 8 02:35:04 (none) kernel: modified: 000000003f7f0000 -
000000003f800000 (reserved)
Oct 8 02:35:04 (none) kernel: modified: 00000000fee00000 -
00000000fee01000 (reserved)
Oct 8 02:35:04 (none) kernel: modified: 00000000fff80000 -
0000000100000000 (reserved)
Oct 8 02:35:04 (none) kernel: initial memory mapped : 0 - 01800000
Oct 8 02:35:04 (none) kernel: found SMP MP-table at [c00ff780] ff780
Oct 8 02:35:04 (none) kernel: init_memory_mapping:
0000000000000000-00000000377fe000
Oct 8 02:35:04 (none) kernel: 0000000000 - 0000400000 page 4k
Oct 8 02:35:04 (none) kernel: 0000400000 - 0037400000 page 2M
Oct 8 02:35:04 (none) kernel: 0037400000 - 00377fe000 page 4k
Oct 8 02:35:04 (none) kernel: kernel direct mapping tables up to
377fe000 @ 15000-1a000
Oct 8 02:35:04 (none) kernel: RAMDISK: 3cf61000 - 3f77f000
Oct 8 02:35:04 (none) kernel: Allocated new RAMDISK: 0157a000 - 03d975=
64
Oct 8 02:35:04 (none) kernel: Move RAMDISK from 000000003cf61000 -
000000003f77e563 to 0157a000 - 03d97563
Oct 8 02:35:04 (none) kernel: ACPI: RSDP 000fbd00 00014 (v00 ACPIAM)
Oct 8 02:35:04 (none) kernel: ACPI: RSDT 3f7a0000 0003C (v01 A_M_I_
OEMRSDT 06000912 MSFT 00000097)
Oct 8 02:35:04 (none) kernel: ACPI: FACP 3f7a0200 00084 (v02 A_M_I_
OEMFACP 06000912 MSFT 00000097)
Oct 8 02:35:04 (none) kernel: ACPI: DSDT 3f7a0430 06292 (v01 P0019
P0019000 00000000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: FACS 3f7ae000 00040
Oct 8 02:35:04 (none) kernel: ACPI: APIC 3f7a0390 0005C (v01 A_M_I_
OEMAPIC 06000912 MSFT 00000097)
Oct 8 02:35:04 (none) kernel: ACPI: MCFG 3f7a03f0 0003C (v01 A_M_I_
OEMMCFG 06000912 MSFT 00000097)
Oct 8 02:35:04 (none) kernel: ACPI: OEMB 3f7ae040 00061 (v01 A_M_I_
AMI_OEM 06000912 MSFT 00000097)
Oct 8 02:35:04 (none) kernel: ACPI: HPET 3f7a66d0 00038 (v01 A_M_I_
OEMHPET 06000912 MSFT 00000097)
Oct 8 02:35:04 (none) kernel: ACPI: SSDT 3f7aeb80 004F0 (v01 PmRef
CpuPm 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: Local APIC address 0xfee00000
Oct 8 02:35:04 (none) kernel: 127MB HIGHMEM available.
Oct 8 02:35:04 (none) kernel: 887MB LOWMEM available.
Oct 8 02:35:04 (none) kernel: mapped low ram: 0 - 377fe000
Oct 8 02:35:04 (none) kernel: low ram: 0 - 377fe000
Oct 8 02:35:04 (none) kernel: Zone PFN ranges:
Oct 8 02:35:04 (none) kernel: DMA 0x00000010 -> 0x00001000
Oct 8 02:35:04 (none) kernel: Normal 0x00001000 -> 0x000377fe
Oct 8 02:35:04 (none) kernel: HighMem 0x000377fe -> 0x0003f7a0
Oct 8 02:35:04 (none) kernel: Movable zone start PFN for each node
Oct 8 02:35:04 (none) kernel: early_node_map[2] active PFN ranges
Oct 8 02:35:04 (none) kernel: 0: 0x00000010 -> 0x0000009f
Oct 8 02:35:04 (none) kernel: 0: 0x00000100 -> 0x0003f7a0
Oct 8 02:35:04 (none) kernel: On node 0 totalpages: 259887
Oct 8 02:35:04 (none) kernel: free_area_init_node: node 0, pgdat
c1418ac0, node_mem_map c3d99200
Oct 8 02:35:04 (none) kernel: DMA zone: 32 pages used for memmap
Oct 8 02:35:04 (none) kernel: DMA zone: 0 pages reserved
Oct 8 02:35:04 (none) kernel: DMA zone: 3951 pages, LIFO batch:0
Oct 8 02:35:04 (none) kernel: Normal zone: 1744 pages used for memmap
Oct 8 02:35:04 (none) kernel: Normal zone: 221486 pages, LIFO batch:31
Oct 8 02:35:04 (none) kernel: HighMem zone: 256 pages used for memmap
Oct 8 02:35:04 (none) kernel: HighMem zone: 32418 pages, LIFO batch:7
Oct 8 02:35:04 (none) kernel: Using APIC driver default
Oct 8 02:35:04 (none) kernel: ACPI: PM-Timer IO Port: 0x808
Oct 8 02:35:04 (none) kernel: ACPI: Local APIC address 0xfee00000
Oct 8 02:35:04 (none) kernel: ACPI: LAPIC (acpi_id[0x01]
lapic_id[0x00] enabled)
Oct 8 02:35:04 (none) kernel: ACPI: LAPIC (acpi_id[0x02]
lapic_id[0x01] enabled)
Oct 8 02:35:04 (none) kernel: ACPI: IOAPIC (id[0x02]
address[0xfec00000] gsi_base[0])
Oct 8 02:35:04 (none) kernel: IOAPIC[0]: apic_id 2, version 32,
address 0xfec00000, GSI 0-23
Oct 8 02:35:04 (none) kernel: ACPI: INT_SRC_OVR (bus 0 bus_irq 0
global_irq 2 dfl dfl)
Oct 8 02:35:04 (none) kernel: ACPI: INT_SRC_OVR (bus 0 bus_irq 9
global_irq 9 high level)
Oct 8 02:35:04 (none) kernel: ACPI: IRQ0 used by override.
Oct 8 02:35:04 (none) kernel: ACPI: IRQ2 used by override.
Oct 8 02:35:04 (none) kernel: ACPI: IRQ9 used by override.
Oct 8 02:35:04 (none) kernel: Using ACPI (MADT) for SMP configuration
information
Oct 8 02:35:04 (none) kernel: ACPI: HPET id: 0xffffffff base: 0xfed000=
00
Oct 8 02:35:04 (none) kernel: SMP: Allowing 2 CPUs, 0 hotplug CPUs
Oct 8 02:35:04 (none) kernel: nr_irqs_gsi: 40
Oct 8 02:35:04 (none) kernel: early_res array is doubled to 64 at
[16000 - 167ff]
Oct 8 02:35:04 (none) kernel: PM: Registered nosave memory:
000000000009f000 - 00000000000a0000
Oct 8 02:35:04 (none) kernel: PM: Registered nosave memory:
00000000000a0000 - 00000000000e0000
Oct 8 02:35:04 (none) kernel: PM: Registered nosave memory:
00000000000e0000 - 0000000000100000
Oct 8 02:35:04 (none) kernel: Allocating PCI resources starting at
3f800000 (gap: 3f800000:bf600000)
Oct 8 02:35:04 (none) kernel: Booting paravirtualized kernel on bare h=
ardware
Oct 8 02:35:04 (none) kernel: setup_percpu: NR_CPUS:8
nr_cpumask_bits:8 nr_cpu_ids:2 nr_node_ids:1
Oct 8 02:35:04 (none) kernel: PERCPU: Embedded 14 pages/cpu @c4800000
s34880 r0 d22464 u2097152
Oct 8 02:35:04 (none) kernel: pcpu-alloc: s34880 r0 d22464 u2097152
alloc=3D1*4194304
Oct 8 02:35:04 (none) kernel: pcpu-alloc: [0] 0 1
Oct 8 02:35:04 (none) kernel: Built 1 zonelists in Zone order,
mobility grouping on. Total pages: 257855
Oct 8 02:35:04 (none) kernel: Kernel command line:
initrd=3D/boot/initrd.img rootdelay=3D10 BOOT_IMAGE=3D/boot/vmlinuz
Oct 8 02:35:04 (none) kernel: PID hash table entries: 4096 (order: 2,
16384 bytes)
Oct 8 02:35:04 (none) kernel: Dentry cache hash table entries: 131072
(order: 7, 524288 bytes)
Oct 8 02:35:04 (none) kernel: Inode-cache hash table entries: 65536
(order: 6, 262144 bytes)
Oct 8 02:35:04 (none) kernel: Enabling fast FPU save and restore... do=
ne.
Oct 8 02:35:04 (none) kernel: Enabling unmasked SIMD FPU exception
support... done.
Oct 8 02:35:04 (none) kernel: Initializing CPU#0
Oct 8 02:35:04 (none) kernel: allocated 5199680 bytes of page_cgroup
Oct 8 02:35:04 (none) kernel: please try 'cgroup_disable=3Dmemory'
option if you don't want memory cgroups
Oct 8 02:35:04 (none) kernel: Subtract (48 early reservations)
Oct 8 02:35:04 (none) kernel: #1 [0000001000 - 0000002000] EX TRAMPO=
LINE
Oct 8 02:35:04 (none) kernel: #2 [0001000000 - 0001572184] TEXT DATA=
BSS
Oct 8 02:35:04 (none) kernel: #3 [0001573000 - 00015791f8] =
BRK
Oct 8 02:35:04 (none) kernel: #4 [00000ff790 - 0000100000] BIOS rese=
rved
Oct 8 02:35:04 (none) kernel: #5 [00000ff780 - 00000ff790] MP-table=
mpf
Oct 8 02:35:04 (none) kernel: #6 [000009fc00 - 00000f1160] BIOS rese=
rved
Oct 8 02:35:04 (none) kernel: #7 [00000f1298 - 00000ff780] BIOS rese=
rved
Oct 8 02:35:04 (none) kernel: #8 [00000f1160 - 00000f1298] MP-table=
mpc
Oct 8 02:35:04 (none) kernel: #9 [0000010000 - 0000011000] TRAMPO=
LINE
Oct 8 02:35:04 (none) kernel: #10 [0000011000 - 0000015000] ACPI W=
AKEUP
Oct 8 02:35:04 (none) kernel: #11 [0000015000 - 0000016000] PG=
TABLE
Oct 8 02:35:04 (none) kernel: #12 [000157a000 - 0003d98000] NEW RA=
MDISK
Oct 8 02:35:04 (none) kernel: #13 [0003d98000 - 0003d99000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #14 [0003d99000 - 0004589000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #15 [00015721c0 - 00015721c4] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #16 [0001572200 - 00015722c0] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #17 [00015722c0 - 0001572314] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #18 [0004589000 - 000458c000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #19 [0001572340 - 000157234c] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #20 [0001572380 - 0001572980] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #21 [0001572980 - 00015729a5] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #22 [00015729c0 - 00015729e7] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #23 [0001572a00 - 0001572b18] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #24 [0001572b40 - 0001572b80] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #25 [0001572b80 - 0001572bc0] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #26 [0001572bc0 - 0001572c00] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #27 [0001572c00 - 0001572c40] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #28 [0001572c40 - 0001572c80] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #29 [0001572c80 - 0001572cc0] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #30 [0001572cc0 - 0001572d00] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #31 [0001572d00 - 0001572d40] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #32 [0001572d40 - 0001572d80] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #33 [0001572d80 - 0001572d90] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #34 [0001572dc0 - 0001572dff] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #35 [0001572e00 - 0001572e3f] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #36 [0004800000 - 000480e000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #37 [0004a00000 - 0004a0e000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #38 [0001572e40 - 0001572e44] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #39 [0001572e80 - 0001572e84] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #40 [0001572ec0 - 0001572ec8] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #41 [0001572f00 - 0001572f08] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #42 [0001572f40 - 0001572fe8] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #43 [0001579200 - 0001579268] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #44 [000458c000 - 0004590000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #45 [0004590000 - 0004610000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #46 [0004610000 - 0004650000] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: #47 [0004a0e000 - 0004f03740] BO=
OTMEM
Oct 8 02:35:04 (none) kernel: Initializing HighMem for node 0
(000377fe:0003f7a0)
Oct 8 02:35:04 (none) kernel: Memory: 978716k/1040000k available
(2986k kernel code, 60832k reserved, 1238k data, 412k init, 130696k
highmem)
Oct 8 02:35:04 (none) kernel: virtual kernel memory layout:
Oct 8 02:35:04 (none) kernel: fixmap : 0xfff16000 - 0xfffff000 ( 93=
2 kB)
Oct 8 02:35:04 (none) kernel: pkmap : 0xff800000 - 0xffc00000 (409=
6 kB)
Oct 8 02:35:04 (none) kernel: vmalloc : 0xf7ffe000 - 0xff7fe000 ( 12=
0 MB)
Oct 8 02:35:04 (none) kernel: lowmem : 0xc0000000 - 0xf77fe000 ( 88=
7 MB)
Oct 8 02:35:04 (none) kernel: .init : 0xc1421000 - 0xc1488000 ( 412 =
kB)
Oct 8 02:35:04 (none) kernel: .data : 0xc12eaacc - 0xc1420340 (1238 =
kB)
Oct 8 02:35:04 (none) kernel: .text : 0xc1000000 - 0xc12eaacc (2986 =
kB)
Oct 8 02:35:04 (none) kernel: Checking if this processor honours the
WP bit even in supervisor mode...Ok.
Oct 8 02:35:04 (none) kernel: SLUB: Genslabs=3D13, HWalign=3D64,
Order=3D0-3, MinObjects=3D0, CPUs=3D2, Nodes=3D1
Oct 8 02:35:04 (none) kernel: Hierarchical RCU implementation.
Oct 8 02:35:04 (none) kernel: RCU-based detection of stalled CPUs is =
disabled.
Oct 8 02:35:04 (none) kernel: Verbose stalled-CPUs detection is disab=
led.
Oct 8 02:35:04 (none) kernel: NR_IRQS:512
Oct 8 02:35:04 (none) kernel: Console: colour VGA+ 80x25
Oct 8 02:35:04 (none) kernel: console [tty0] enabled
Oct 8 02:35:04 (none) kernel: hpet clockevent registered
Oct 8 02:35:04 (none) kernel: Fast TSC calibration using PIT
Oct 8 02:35:04 (none) kernel: Detected 1600.086 MHz processor.
Oct 8 02:35:04 (none) kernel: Calibrating delay loop (skipped), value
calculated using timer frequency.. 3201.51 BogoMIPS (lpj=3D5333620)
Oct 8 02:35:04 (none) kernel: pid_max: default: 32768 minimum: 301
Oct 8 02:35:04 (none) kernel: Security Framework initialized
Oct 8 02:35:04 (none) kernel: Mount-cache hash table entries: 512
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys ns
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys cpuacct
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys memory
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys devices
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys freezer
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys net_cls
Oct 8 02:35:04 (none) kernel: Initializing cgroup subsys blkio
Oct 8 02:35:04 (none) kernel: CPU: Physical Processor ID: 0
Oct 8 02:35:04 (none) kernel: CPU: Processor Core ID: 0
Oct 8 02:35:04 (none) kernel: mce: CPU supports 5 MCE banks
Oct 8 02:35:04 (none) kernel: CPU0: Thermal monitoring enabled (TM2)
Oct 8 02:35:04 (none) kernel: using mwait in idle threads.
Oct 8 02:35:04 (none) kernel: Performance Events: PEBS fmt0+, Atom
events, Intel PMU driver.
Oct 8 02:35:04 (none) kernel: ... version: 3
Oct 8 02:35:04 (none) kernel: ... bit width: 40
Oct 8 02:35:04 (none) kernel: ... generic registers: 2
Oct 8 02:35:04 (none) kernel: ... value mask: 000000ffffff=
ffff
Oct 8 02:35:04 (none) kernel: ... max period: 000000007fff=
ffff
Oct 8 02:35:04 (none) kernel: ... fixed-purpose events: 3
Oct 8 02:35:04 (none) kernel: ... event mask: 000000070000=
0003
Oct 8 02:35:04 (none) kernel: ACPI: Core revision 20100428
Oct 8 02:35:04 (none) kernel: Enabling APIC mode: Flat. Using 1 I/O =
APICs
Oct 8 02:35:04 (none) kernel: ..TIMER: vector=3D0x30 apic1=3D0 pin1=3D=
2
apic2=3D-1 pin2=3D-1
Oct 8 02:35:04 (none) kernel: CPU0: Intel(R) Atom(TM) CPU N270 @
1.60GHz stepping 02
Oct 8 02:35:04 (none) kernel: APIC calibration not consistent with
PM-Timer: 159ms instead of 100ms
Oct 8 02:35:04 (none) kernel: APIC delta adjusted to PM-Timer: 833332 =
(1333327)
Oct 8 02:35:04 (none) kernel: Booting Node 0, Processors #1 Ok.
Oct 8 02:35:04 (none) kernel: Initializing CPU#1
Oct 8 02:35:04 (none) kernel: Brought up 2 CPUs
Oct 8 02:35:04 (none) kernel: Total of 2 processors activated
(6402.80 BogoMIPS).
Oct 8 02:35:04 (none) kernel: devtmpfs: initialized
Oct 8 02:35:04 (none) kernel: NET: Registered protocol family 16
Oct 8 02:35:04 (none) kernel: ACPI: bus type pci registered
Oct 8 02:35:04 (none) kernel: PCI: MMCONFIG for domain 0000 [bus
00-3f] at [mem 0xe0000000-0xe3ffffff] (base 0xe0000000)
Oct 8 02:35:04 (none) kernel: PCI: not using MMCONFIG
Oct 8 02:35:04 (none) kernel: PCI: PCI BIOS revision 3.00 entry at
0xf0031, last bus=3D4
Oct 8 02:35:04 (none) kernel: PCI: Using configuration type 1 for base=
access
Oct 8 02:35:04 (none) kernel: bio: create slab <bio-0> at 0
Oct 8 02:35:04 (none) kernel: ACPI: EC: Look up EC in DSDT
Oct 8 02:35:04 (none) kernel: ACPI: Executed 1 blocks of module-level
executable AML code
Oct 8 02:35:04 (none) kernel: ACPI: SSDT 3f7ae180 0023C (v01 PmRef
Cpu0Ist 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: Dynamic OEM Table Load:
Oct 8 02:35:04 (none) kernel: ACPI: SSDT (null) 0023C (v01 PmRef
Cpu0Ist 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: SSDT 3f7ae450 00724 (v01 PmRef
Cpu0Cst 00003001 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: Dynamic OEM Table Load:
Oct 8 02:35:04 (none) kernel: ACPI: SSDT (null) 00724 (v01 PmRef
Cpu0Cst 00003001 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: SSDT 3f7ae0b0 000CC (v01 PmRef
Cpu1Ist 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: Dynamic OEM Table Load:
Oct 8 02:35:04 (none) kernel: ACPI: SSDT (null) 000CC (v01 PmRef
Cpu1Ist 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: SSDT 3f7ae3c0 00085 (v01 PmRef
Cpu1Cst 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: Dynamic OEM Table Load:
Oct 8 02:35:04 (none) kernel: ACPI: SSDT (null) 00085 (v01 PmRef
Cpu1Cst 00003000 INTL 20060113)
Oct 8 02:35:04 (none) kernel: ACPI: Interpreter enabled
Oct 8 02:35:04 (none) kernel: ACPI: (supports S0 S3 S4 S5)
Oct 8 02:35:04 (none) kernel: ACPI: Using IOAPIC for interrupt routing
Oct 8 02:35:04 (none) kernel: PCI: MMCONFIG for domain 0000 [bus
00-3f] at [mem 0xe0000000-0xe3ffffff] (base 0xe0000000)
Oct 8 02:35:04 (none) kernel: PCI: MMCONFIG at [mem
0xe0000000-0xe3ffffff] reserved in ACPI motherboard resources
Oct 8 02:35:04 (none) kernel: PCI: Using MMCONFIG for extended config =
space
Oct 8 02:35:04 (none) kernel: ACPI: EC: GPE =3D 0x1c, I/O:
command/status =3D 0x66, data =3D 0x62
Oct 8 02:35:04 (none) kernel: ACPI: No dock devices found.
Oct 8 02:35:04 (none) kernel: PCI: Using host bridge windows from
ACPI; if necessary, use "pci=3Dnocrs" and report a bug
Oct 8 02:35:04 (none) kernel: ACPI: PCI Root Bridge [PCI0] (domain
0000 [bus 00-ff])
Oct 8 02:35:04 (none) kernel: pci_root PNP0A08:00: host bridge window
[io 0x0000-0x0cf7]
Oct 8 02:35:04 (none) kernel: pci_root PNP0A08:00: host bridge window
[io 0x0d00-0xffff]
Oct 8 02:35:04 (none) kernel: pci_root PNP0A08:00: host bridge window
[mem 0x000a0000-0x000bffff]
Oct 8 02:35:04 (none) kernel: pci_root PNP0A08:00: host bridge window
[mem 0x000d0000-0x000dffff]
Oct 8 02:35:04 (none) kernel: pci_root PNP0A08:00: host bridge window
[mem 0x3f800000-0xffffffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:02.0: reg 10: [mem
0xfbd00000-0xfbd7ffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:02.0: reg 14: [io 0xdc80-0x=
dc87]
Oct 8 02:35:04 (none) kernel: pci 0000:00:02.0: reg 18: [mem
0xd0000000-0xdfffffff pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:02.0: reg 1c: [mem
0xfbcc0000-0xfbcfffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:02.1: reg 10: [mem
0xfbd80000-0xfbdfffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1b.0: reg 10: [mem
0xfbcb8000-0xfbcbbfff 64bit]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1b.0: PME# supported from
D0 D3hot D3cold
Oct 8 02:35:04 (none) kernel: pci 0000:00:1b.0: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: PME# supported from
D0 D3hot D3cold
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: PME# supported from
D0 D3hot D3cold
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: PME# supported from
D0 D3hot D3cold
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.0: reg 20: [io 0xd480-0x=
d49f]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.1: reg 20: [io 0xd800-0x=
d81f]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.2: reg 20: [io 0xd880-0x=
d89f]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.3: reg 20: [io 0xdc00-0x=
dc1f]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.7: reg 10: [mem
0xfbcb7c00-0xfbcb7fff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.7: PME# supported from
D0 D3hot D3cold
Oct 8 02:35:04 (none) kernel: pci 0000:00:1d.7: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.0: quirk: [io
0x0800-0x087f] claimed by ICH6 ACPI/GPIO/TCO
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.0: quirk: [io
0x0480-0x04bf] claimed by ICH6 GPIO
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.0: ICH7 LPC Generic IO
decode 1 PIO at 0380 (mask 0003)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.0: ICH7 LPC Generic IO
decode 2 PIO at 0290 (mask 0007)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.0: ICH7 LPC Generic IO
decode 3 PIO at 0068 (mask 0003)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: reg 10: [io 0x0000-0x=
0007]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: reg 14: [io 0x0000-0x=
0003]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: reg 18: [io 0x0000-0x=
0007]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: reg 1c: [io 0x0000-0x=
0003]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: reg 20: [io 0xffa0-0x=
ffaf]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: PME# supported from D3=
hot
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.2: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1f.3: reg 20: [io 0x0400-0x=
041f]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: PCI bridge to [bus 03-=
03]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: bridge window [io
0xf000-0x0000] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: bridge window [mem
0xfff00000-0x000fffff] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: bridge window [mem
0xfff00000-0x000fffff pref] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:02:00.0: reg 10: [mem
0xfbfc0000-0xfbffffff 64bit]
Oct 8 02:35:04 (none) kernel: pci 0000:02:00.0: reg 18: [io 0xec80-0x=
ecff]
Oct 8 02:35:04 (none) kernel: pci 0000:02:00.0: PME# supported from
D3hot D3cold
Oct 8 02:35:04 (none) kernel: pci 0000:02:00.0: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: PCI bridge to [bus 02-=
02]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: bridge window [io
0xe000-0xefff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: bridge window [mem
0xfbf00000-0xfbffffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: bridge window [mem
0xfff00000-0x000fffff pref] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:01:00.0: reg 10: [mem
0xfbef0000-0xfbefffff 64bit]
Oct 8 02:35:04 (none) kernel: pci 0000:01:00.0: supports D1
Oct 8 02:35:04 (none) kernel: pci 0000:01:00.0: PME# supported from D0=
D1 D3hot
Oct 8 02:35:04 (none) kernel: pci 0000:01:00.0: PME# disabled
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: PCI bridge to [bus 01-=
01]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: bridge window [io
0xf000-0x0000] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: bridge window [mem
0xfbe00000-0xfbefffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: bridge window [mem
0xfff00000-0x000fffff pref] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: PCI bridge to [bus
04-04] (subtractive decode)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [io
0xf000-0x0000] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem
0xfff00000-0x000fffff] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem
0xfff00000-0x000fffff pref] (disabled)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [io
0x0000-0x0cf7] (subtractive decode)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [io
0x0d00-0xffff] (subtractive decode)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem
0x000a0000-0x000bffff] (subtractive decode)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem
0x000d0000-0x000dffff] (subtractive decode)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem
0x3f800000-0xffffffff] (subtractive decode)
Oct 8 02:35:04 (none) kernel: pci_bus 0000:00: on NUMA node 0
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Routing Table
[\_SB_.PCI0._PRT]
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Routing Table
[\_SB_.PCI0.P0P4._PRT]
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Routing Table
[\_SB_.PCI0.P0P6._PRT]
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Routing Table
[\_SB_.PCI0.P0P5._PRT]
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKA] (IRQs 3
4 *5 6 7 10 11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKB] (IRQs 3
4 5 6 7 *10 11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKC] (IRQs 3
4 5 6 7 10 *11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKD] (IRQs 3
4 5 6 7 10 *11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKE] (IRQs 3
4 5 6 *7 10 11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKF] (IRQs 3
*4 5 6 7 10 11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKG] (IRQs 3
4 5 6 7 10 *11 12 14 15)
Oct 8 02:35:04 (none) kernel: ACPI: PCI Interrupt Link [LNKH] (IRQs
*3 4 5 6 7 10 11 12 14 15)
Oct 8 02:35:04 (none) kernel: HEST: Table is not found!
Oct 8 02:35:04 (none) kernel: vgaarb: device added:
PCI:0000:00:02.0,decodes=3Dio+mem,owns=3Dio+mem,locks=3Dnone
Oct 8 02:35:04 (none) kernel: vgaarb: loaded
Oct 8 02:35:04 (none) kernel: PCI: Using ACPI for IRQ routing
Oct 8 02:35:04 (none) kernel: PCI: pci_cache_line_size set to 64 bytes
Oct 8 02:35:04 (none) kernel: reserve RAM buffer: 000000000009fc00 -
000000000009ffff
Oct 8 02:35:04 (none) kernel: reserve RAM buffer: 000000003f7a0000 -
000000003fffffff
Oct 8 02:35:04 (none) kernel: NetLabel: Initializing
Oct 8 02:35:04 (none) kernel: NetLabel: domain hash size =3D 128
Oct 8 02:35:04 (none) kernel: NetLabel: protocols =3D UNLABELED CIPSO=
v4
Oct 8 02:35:04 (none) kernel: NetLabel: unlabeled traffic allowed by =
default
Oct 8 02:35:04 (none) kernel: HPET: 3 timers in total, 0 timers will
be used for per-cpu timer
Oct 8 02:35:04 (none) kernel: hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
Oct 8 02:35:04 (none) kernel: hpet0: 3 comparators, 64-bit 14.318180
MHz counter
Oct 8 02:35:04 (none) kernel: Switching to clocksource tsc
Oct 8 02:35:04 (none) kernel: pnp: PnP ACPI init
Oct 8 02:35:04 (none) kernel: ACPI: bus type pnp registered
Oct 8 02:35:04 (none) kernel: pnp: PnP ACPI: found 13 devices
Oct 8 02:35:04 (none) kernel: ACPI: ACPI bus type pnp unregistered
Oct 8 02:35:04 (none) kernel: system 00:01: [mem
0xfed13000-0xfed19fff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [io 0x025c-0x025f] has
been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [io 0x0380-0x0383] has
been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [io 0x0400-0x041f] has
been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [io 0x04d0-0x04d1] has
been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [io 0x0800-0x087f] has
been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [io 0x0480-0x04bf] has
been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [mem
0x8c000000-0x8c01ffff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [mem
0xfed1c000-0xfed1ffff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [mem
0xfed20000-0xfed3ffff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [mem
0xfed50000-0xfed8ffff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [mem
0xffb00000-0xffbfffff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:08: [mem
0xfff00000-0xffffffff] could not be reserved
Oct 8 02:35:04 (none) kernel: system 00:0a: [mem
0xfec00000-0xfec00fff] could not be reserved
Oct 8 02:35:04 (none) kernel: system 00:0a: [mem
0xfee00000-0xfee00fff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:0b: [mem
0xe0000000-0xe3ffffff] has been reserved
Oct 8 02:35:04 (none) kernel: system 00:0c: [mem
0x00000000-0x0009ffff] could not be reserved
Oct 8 02:35:04 (none) kernel: system 00:0c: [mem
0x000c0000-0x000cffff] could not be reserved
Oct 8 02:35:04 (none) kernel: system 00:0c: [mem
0x000e0000-0x000fffff] could not be reserved
Oct 8 02:35:04 (none) kernel: system 00:0c: [mem
0x00100000-0x3f7fffff] could not be reserved
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: BAR 14: assigned [mem
0x3f800000-0x3f9fffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: BAR 15: assigned [mem
0x3fa00000-0x3fbfffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: BAR 15: assigned [mem
0x3fc00000-0x3fdfffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: BAR 15: assigned [mem
0x3fe00000-0x3fffffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: BAR 13: assigned [io
0x1000-0x1fff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: BAR 13: assigned [io
0x2000-0x2fff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: PCI bridge to [bus 03-=
03]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: bridge window [io
0x1000-0x1fff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: bridge window [mem
0x3f800000-0x3f9fffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: bridge window [mem
0x3fa00000-0x3fbfffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: PCI bridge to [bus 02-=
02]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: bridge window [io
0xe000-0xefff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: bridge window [mem
0xfbf00000-0xfbffffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: bridge window [mem
0x3fc00000-0x3fdfffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: PCI bridge to [bus 01-=
01]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: bridge window [io
0x2000-0x2fff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: bridge window [mem
0xfbe00000-0xfbefffff]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: bridge window [mem
0x3fe00000-0x3fffffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: PCI bridge to [bus 04-=
04]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [io d=
isabled]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem d=
isabled]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: bridge window [mem
pref disabled]
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: enabling device (0104 =
-> 0107)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: PCI INT A -> GSI 16
(level, low) -> IRQ 16
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.0: setting latency timer =
to 64
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: PCI INT B -> GSI 17
(level, low) -> IRQ 17
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.1: setting latency timer =
to 64
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: enabling device (0106 =
-> 0107)
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: PCI INT C -> GSI 18
(level, low) -> IRQ 18
Oct 8 02:35:04 (none) kernel: pci 0000:00:1c.2: setting latency timer =
to 64
Oct 8 02:35:04 (none) kernel: pci 0000:00:1e.0: setting latency timer =
to 64
Oct 8 02:35:04 (none) kernel: pci_bus 0000:00: resource 4 [io 0x0000-=
0x0cf7]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:00: resource 5 [io 0x0d00-=
0xffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:00: resource 6 [mem
0x000a0000-0x000bffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:00: resource 7 [mem
0x000d0000-0x000dffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:00: resource 8 [mem
0x3f800000-0xffffffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:03: resource 0 [io 0x1000-=
0x1fff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:03: resource 1 [mem
0x3f800000-0x3f9fffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:03: resource 2 [mem
0x3fa00000-0x3fbfffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:02: resource 0 [io 0xe000-=
0xefff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:02: resource 1 [mem
0xfbf00000-0xfbffffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:02: resource 2 [mem
0x3fc00000-0x3fdfffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:01: resource 0 [io 0x2000-=
0x2fff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:01: resource 1 [mem
0xfbe00000-0xfbefffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:01: resource 2 [mem
0x3fe00000-0x3fffffff 64bit pref]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:04: resource 4 [io 0x0000-=
0x0cf7]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:04: resource 5 [io 0x0d00-=
0xffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:04: resource 6 [mem
0x000a0000-0x000bffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:04: resource 7 [mem
0x000d0000-0x000dffff]
Oct 8 02:35:04 (none) kernel: pci_bus 0000:04: resource 8 [mem
0x3f800000-0xffffffff]
Oct 8 02:35:04 (none) kernel: NET: Registered protocol family 2
Oct 8 02:35:04 (none) kernel: IP route cache hash table entries:
32768 (order: 5, 131072 bytes)
Oct 8 02:35:04 (none) kernel: TCP established hash table entries:
131072 (order: 8, 1048576 bytes)
Oct 8 02:35:04 (none) kernel: TCP bind hash table entries: 65536
(order: 7, 524288 bytes)
Oct 8 02:35:04 (none) kernel: TCP: Hash tables configured
(established 131072 bind 65536)
Oct 8 02:35:04 (none) kernel: TCP reno registered
Oct 8 02:35:04 (none) kernel: UDP hash table entries: 512 (order: 2,
16384 bytes)
Oct 8 02:35:04 (none) kernel: UDP-Lite hash table entries: 512
(order: 2, 16384 bytes)
Oct 8 02:35:04 (none) kernel: NET: Registered protocol family 1
Oct 8 02:35:04 (none) kernel: pci 0000:00:02.0: Boot video device
Oct 8 02:35:04 (none) kernel: PCI: CLS 32 bytes, default 64
Oct 8 02:35:04 (none) kernel: Unpacking initramfs...
Oct 8 02:35:04 (none) kernel: Freeing initrd memory: 41080k freed
Oct 8 02:35:04 (none) kernel: apm: BIOS version 1.2 Flags 0x03
(Driver version 1.16ac)
Oct 8 02:35:04 (none) kernel: apm: disabled - APM is not SMP safe.
Oct 8 02:35:04 (none) kernel: Scanning for low memory corruption
every 60 seconds
Oct 8 02:35:04 (none) kernel: audit: initializing netlink socket (disa=
bled)
Oct 8 02:35:04 (none) kernel: type=3D2000 audit(1286505283.363:1): ini=
tialized
Oct 8 02:35:04 (none) kernel: highmem bounce pool size: 64 pages
Oct 8 02:35:04 (none) kernel: VFS: Disk quotas dquot_6.5.2
Oct 8 02:35:04 (none) kernel: Dquot-cache hash table entries: 1024
(order 0, 4096 bytes)
Oct 8 02:35:04 (none) kernel: msgmni has been set to 1736
Oct 8 02:35:04 (none) kernel: alg: No test for stdrng (krng)
Oct 8 02:35:04 (none) kernel: Block layer SCSI generic (bsg) driver
version 0.4 loaded (major 254)
Oct 8 02:35:04 (none) kernel: io scheduler noop registered
Oct 8 02:35:04 (none) kernel: io scheduler deadline registered
Oct 8 02:35:04 (none) kernel: io scheduler cfq registered (default)
Oct 8 02:35:04 (none) kernel: pcieport 0000:00:1c.0: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: pcieport 0000:00:1c.0: irq 40 for MSI/MS=
I-X
Oct 8 02:35:04 (none) kernel: pcieport 0000:00:1c.1: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: pcieport 0000:00:1c.1: irq 41 for MSI/MS=
I-X
Oct 8 02:35:04 (none) kernel: pcieport 0000:00:1c.2: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: pcieport 0000:00:1c.2: irq 42 for MSI/MS=
I-X
Oct 8 02:35:04 (none) kernel: ERST: Table is not found!
Oct 8 02:35:04 (none) kernel: isapnp: Scanning for PnP cards...
Oct 8 02:35:04 (none) kernel: isapnp: No Plug & Play device found
Oct 8 02:35:04 (none) kernel: Serial: 8250/16550 driver, 4 ports, IRQ
sharing disabled
Oct 8 02:35:04 (none) kernel: PNP: PS/2 Controller
[PNP0303:PS2K,PNP0f13:PS2M] at 0x60,0x64 irq 1,12
Oct 8 02:35:04 (none) kernel: serio: i8042 KBD port at 0x60,0x64 irq 1
Oct 8 02:35:04 (none) kernel: serio: i8042 AUX port at 0x60,0x64 irq 1=
2
Oct 8 02:35:04 (none) kernel: mice: PS/2 mouse device common for all m=
ice
Oct 8 02:35:04 (none) kernel: cpuidle: using governor ladder
Oct 8 02:35:04 (none) kernel: cpuidle: using governor menu
Oct 8 02:35:04 (none) kernel: TCP cubic registered
Oct 8 02:35:04 (none) kernel: NET: Registered protocol family 17
Oct 8 02:35:04 (none) kernel: Using IPI No-Shortcut mode
Oct 8 02:35:04 (none) kernel: PM: Resume from disk failed.
Oct 8 02:35:04 (none) kernel: registered taskstats version 1
Oct 8 02:35:04 (none) kernel: Initalizing network drop monitor service
Oct 8 02:35:04 (none) kernel: Freeing unused kernel memory: 412k freed
Oct 8 02:35:04 (none) kernel: input: AT Translated Set 2 keyboard as
/devices/platform/i8042/serio0/input/input0
Oct 8 02:35:04 (none) kernel: ACPI: AC Adapter [AC0] (off-line)
Oct 8 02:35:04 (none) kernel: ACPI: Battery Slot [BAT0] (battery prese=
nt)
Oct 8 02:35:04 (none) kernel: input: Lid Switch as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input1
Oct 8 02:35:04 (none) kernel: ACPI: Lid Switch [LID]
Oct 8 02:35:04 (none) kernel: input: Sleep Button as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input2
Oct 8 02:35:04 (none) kernel: ACPI: Sleep Button [SLPB]
Oct 8 02:35:04 (none) kernel: input: Power Button as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input3
Oct 8 02:35:04 (none) kernel: ACPI: Power Button [PWRB]
Oct 8 02:35:04 (none) kernel: input: Power Button as
/devices/LNXSYSTM:00/LNXPWRBN:00/input/input4
Oct 8 02:35:04 (none) kernel: ACPI: Power Button [PWRF]
Oct 8 02:35:04 (none) kernel: ACPI: acpi_idle registered with cpuidle
Oct 8 02:35:04 (none) kernel: Monitor-Mwait will be used to enter C-1 =
state
Oct 8 02:35:04 (none) kernel: Monitor-Mwait will be used to enter C-2 =
state
Oct 8 02:35:04 (none) kernel: Monitor-Mwait will be used to enter C-3 =
state
Oct 8 02:35:04 (none) kernel: Marking TSC unstable due to TSC halts in=
idle
Oct 8 02:35:04 (none) kernel: Switching to clocksource hpet
Oct 8 02:35:04 (none) kernel: thermal LNXTHERM:01: registered as therm=
al_zone0
Oct 8 02:35:04 (none) kernel: ACPI: Thermal Zone [TZ00] (59 C)
Oct 8 02:35:04 (none) kernel: input: Video Bus as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input5
Oct 8 02:35:04 (none) kernel: ACPI: Video Device [VGA] (multi-head:
yes rom: no post: no)
Oct 8 02:35:04 (none) kernel: Linux agpgart interface v0.103
Oct 8 02:35:04 (none) kernel: agpgart-intel 0000:00:00.0: Intel 945GME=
Chipset
Oct 8 02:35:04 (none) kernel: agpgart-intel 0000:00:00.0: detected
7932K stolen memory
Oct 8 02:35:04 (none) kernel: agpgart-intel 0000:00:00.0: AGP
aperture is 256M @ 0xd0000000
Oct 8 02:35:04 (none) kernel: input: PC Speaker as
/devices/platform/pcspkr/input/input6
Oct 8 02:35:04 (none) kernel: pci_hotplug: PCI Hot Plug PCI Core versi=
on: 0.5
Oct 8 02:35:04 (none) kernel: eeepc_laptop: Eee PC Hotkey Driver
Oct 8 02:35:04 (none) kernel: eeepc_laptop: Hotkey init flags 0x41
Oct 8 02:35:04 (none) kernel: eeepc_laptop: TYPE (2000000) not
reported by BIOS, enabling anyway
Oct 8 02:35:04 (none) kernel: eeepc_laptop: PANELPOWER (4000000) not
reported by BIOS, enabling anyway
Oct 8 02:35:04 (none) kernel: eeepc_laptop: TPD (8000000) not
reported by BIOS, enabling anyway
Oct 8 02:35:04 (none) kernel: eeepc_laptop: Get control methods
supported: 0xe101713
Oct 8 02:35:04 (none) kernel: input: Asus EeePC extra buttons as
/devices/platform/eeepc/input/input7
Oct 8 02:35:04 (none) kernel: Registered led device: eeepc::touchpad
Oct 8 02:35:04 (none) kernel: rtc_cmos 00:03: RTC can wake from S4
Oct 8 02:35:04 (none) kernel: rtc_cmos 00:03: rtc core: registered
rtc_cmos as rtc0
Oct 8 02:35:04 (none) kernel: rtc0: alarms up to one month, 114 bytes
nvram, hpet irqs
Oct 8 02:35:04 (none) kernel: HDA Intel 0000:00:1b.0: PCI INT A ->
GSI 16 (level, low) -> IRQ 16
Oct 8 02:35:04 (none) kernel: HDA Intel 0000:00:1b.0: irq 43 for MSI/M=
SI-X
Oct 8 02:35:04 (none) kernel: HDA Intel 0000:00:1b.0: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: SCSI subsystem initialized
Oct 8 02:35:04 (none) kernel: libata version 3.00 loaded.
Oct 8 02:35:04 (none) kernel: ata_piix 0000:00:1f.2: version 2.13
Oct 8 02:35:04 (none) kernel: ata_piix 0000:00:1f.2: PCI INT B -> GSI
19 (level, low) -> IRQ 19
Oct 8 02:35:04 (none) kernel: ata_piix 0000:00:1f.2: MAP [ P0 P2 IDE I=
DE ]
Oct 8 02:35:04 (none) kernel: ata_piix 0000:00:1f.2: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: scsi0 : ata_piix
Oct 8 02:35:04 (none) kernel: scsi1 : ata_piix
Oct 8 02:35:04 (none) kernel: ata1: SATA max UDMA/133 cmd 0x1f0 ctl
0x3f6 bmdma 0xffa0 irq 14
Oct 8 02:35:04 (none) kernel: ata2: PATA max UDMA/100 cmd 0x170 ctl
0x376 bmdma 0xffa8 irq 15
Oct 8 02:35:04 (none) kernel: ata1.00: ATA-8: ASUS-JM S41 SSD,
02.10102, max UDMA/100
Oct 8 02:35:04 (none) kernel: ata1.00: 63078400 sectors, multi 0: LBA
Oct 8 02:35:04 (none) kernel: ata1.00: configured for UDMA/100
Oct 8 02:35:04 (none) kernel: scsi 0:0:0:0: Direct-Access ATA
ASUS-JM S41 SSD 02.1 PQ: 0 ANSI: 5
Oct 8 02:35:04 (none) kernel: ATL1E 0000:02:00.0: PCI INT A -> GSI 17
(level, low) -> IRQ 17
Oct 8 02:35:04 (none) kernel: ATL1E 0000:02:00.0: setting latency time=
r to 64
Oct 8 02:35:04 (none) kernel: sd 0:0:0:0: [sda] 63078400 512-byte
logical blocks: (32.2 GB/30.0 GiB)
Oct 8 02:35:04 (none) kernel: sd 0:0:0:0: [sda] Write Protect is off
Oct 8 02:35:04 (none) kernel: sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 0=
0
Oct 8 02:35:04 (none) kernel: sd 0:0:0:0: [sda] Write cache:
disabled, read cache: enabled, doesn't support DPO or FUA
Oct 8 02:35:04 (none) kernel: sda: sda1 sda2 sda3
Oct 8 02:35:04 (none) kernel: sd 0:0:0:0: [sda] Attached SCSI disk
Oct 8 02:35:04 (none) kernel: sd 0:0:0:0: Attached scsi generic sg0 ty=
pe 0
Oct 8 02:35:04 (none) kernel: cfg80211: Calling CRDA to update world
regulatory domain
Oct 8 02:35:04 (none) kernel: cfg80211: World regulatory domain update=
d:
Oct 8 02:35:04 (none) kernel: (start_freq - end_freq @ bandwidth),
(max_antenna_gain, max_eirp)
Oct 8 02:35:04 (none) kernel: (2402000 KHz - 2472000 KHz @ 40000
KHz), (300 mBi, 2000 mBm)
Oct 8 02:35:04 (none) kernel: (2457000 KHz - 2482000 KHz @ 20000
KHz), (300 mBi, 2000 mBm)
Oct 8 02:35:04 (none) kernel: (2474000 KHz - 2494000 KHz @ 20000
KHz), (300 mBi, 2000 mBm)
Oct 8 02:35:04 (none) kernel: (5170000 KHz - 5250000 KHz @ 40000
KHz), (300 mBi, 2000 mBm)
Oct 8 02:35:04 (none) kernel: (5735000 KHz - 5835000 KHz @ 40000
KHz), (300 mBi, 2000 mBm)
Oct 8 02:35:04 (none) kernel: ath9k 0000:01:00.0: PCI INT A -> GSI 18
(level, low) -> IRQ 18
Oct 8 02:35:04 (none) kernel: ath9k 0000:01:00.0: setting latency time=
r to 64
Oct 8 02:35:04 (none) kernel: ath: EEPROM regdomain: 0x60
Oct 8 02:35:04 (none) kernel: ath: EEPROM indicates we should expect
a direct regpair map
Oct 8 02:35:04 (none) kernel: ath: Country alpha2 being used: 00
Oct 8 02:35:04 (none) kernel: ath: Regpair used: 0x60
Oct 8 02:35:04 (none) kernel: phy0: Selected rate control algorithm
'ath9k_rate_control'
Oct 8 02:35:04 (none) kernel: Registered led device: ath9k-phy0::radio
Oct 8 02:35:04 (none) kernel: Registered led device: ath9k-phy0::assoc
Oct 8 02:35:04 (none) kernel: Registered led device: ath9k-phy0::tx
Oct 8 02:35:04 (none) kernel: Registered led device: ath9k-phy0::rx
Oct 8 02:35:04 (none) kernel: phy0: Atheros AR9280 Rev:2 mem=3D0xf8700=
000, irq=3D18
Oct 8 02:35:04 (none) kernel: usbcore: registered new interface driver=
usbfs
Oct 8 02:35:04 (none) kernel: usbcore: registered new interface driver=
hub
Oct 8 02:35:04 (none) kernel: usbcore: registered new device driver us=
b
Oct 8 02:35:04 (none) kernel: ehci_hcd: USB 2.0 'Enhanced' Host
Controller (EHCI) Driver
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: PCI INT A -> GSI
23 (level, low) -> IRQ 23
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: EHCI Host Control=
ler
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: new USB bus
registered, assigned bus number 1
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: using broken
periodic workaround
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: debug port 1
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: cache line size
of 32 is not supported
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: irq 23, io mem 0x=
fbcb7c00
Oct 8 02:35:04 (none) kernel: ehci_hcd 0000:00:1d.7: USB 2.0 started, =
EHCI 1.00
Oct 8 02:35:04 (none) kernel: hub 1-0:1.0: USB hub found
Oct 8 02:35:04 (none) kernel: hub 1-0:1.0: 8 ports detected
Oct 8 02:35:04 (none) kernel: uhci_hcd: USB Universal Host Controller
Interface driver
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.0: PCI INT A -> GSI
23 (level, low) -> IRQ 23
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.0: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.0: UHCI Host Control=
ler
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.0: new USB bus
registered, assigned bus number 2
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.0: irq 23, io base 0=
x0000d480
Oct 8 02:35:04 (none) kernel: hub 2-0:1.0: USB hub found
Oct 8 02:35:04 (none) kernel: hub 2-0:1.0: 2 ports detected
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.1: PCI INT B -> GSI
22 (level, low) -> IRQ 22
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.1: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.1: UHCI Host Control=
ler
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.1: new USB bus
registered, assigned bus number 3
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.1: irq 22, io base 0=
x0000d800
Oct 8 02:35:04 (none) kernel: hub 3-0:1.0: USB hub found
Oct 8 02:35:04 (none) kernel: hub 3-0:1.0: 2 ports detected
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.2: PCI INT C -> GSI
21 (level, low) -> IRQ 21
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.2: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.2: UHCI Host Control=
ler
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.2: new USB bus
registered, assigned bus number 4
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.2: irq 21, io base 0=
x0000d880
Oct 8 02:35:04 (none) kernel: hub 4-0:1.0: USB hub found
Oct 8 02:35:04 (none) kernel: hub 4-0:1.0: 2 ports detected
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.3: PCI INT D -> GSI
20 (level, low) -> IRQ 20
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.3: setting latency
timer to 64
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.3: UHCI Host Control=
ler
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.3: new USB bus
registered, assigned bus number 5
Oct 8 02:35:04 (none) kernel: uhci_hcd 0000:00:1d.3: irq 20, io base 0=
x0000dc00
Oct 8 02:35:04 (none) kernel: hub 5-0:1.0: USB hub found
Oct 8 02:35:04 (none) kernel: hub 5-0:1.0: 2 ports detected
Oct 8 02:35:04 (none) kernel: usb 1-3: new high speed USB device
using ehci_hcd and address 2
Oct 8 02:35:04 (none) kernel: usb 1-5: new high speed USB device
using ehci_hcd and address 3
Oct 8 02:35:04 (none) kernel: hub 1-0:1.0: unable to enumerate USB
device on port 7
Oct 8 02:35:04 (none) kernel: usb 1-8: new high speed USB device
using ehci_hcd and address 5
Oct 8 02:35:04 (none) kernel: Initializing USB Mass Storage driver...
Oct 8 02:35:04 (none) kernel: scsi2 : usb-storage 1-3:1.0
Oct 8 02:35:04 (none) kernel: scsi3 : usb-storage 1-5:1.0
Oct 8 02:35:04 (none) kernel: usbcore: registered new interface
driver usb-storage
Oct 8 02:35:04 (none) kernel: USB Mass Storage support registered.
Oct 8 02:35:04 (none) kernel: scsi 2:0:0:0: Direct-Access usb 2.0
Flash Disk 5.00 PQ: 0 ANSI: 2
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: Attached scsi generic sg1 ty=
pe 0
Oct 8 02:35:04 (none) kernel: scsi 3:0:0:0: Direct-Access Multi
Flash Reader 1.00 PQ: 0 ANSI: 0
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] 2048000 512-byte
logical blocks: (1.04 GB/1000 MiB)
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: Attached scsi generic sg2 ty=
pe 0
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] Write Protect is off
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] Mode Sense: 0b 00 00 0=
8
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] Assuming drive cache:
write through
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] Assuming drive cache:
write through
Oct 8 02:35:04 (none) kernel: sdb: sdb1
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] Assuming drive cache:
write through
Oct 8 02:35:04 (none) kernel: sd 2:0:0:0: [sdb] Attached SCSI removabl=
e disk
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] 245504 512-byte
logical blocks: (125 MB/119 MiB)
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] Write Protect is off
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] Mode Sense: 03 00 00 0=
0
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] Assuming drive cache:
write through
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] Assuming drive cache:
write through
Oct 8 02:35:04 (none) kernel: sdc: sdc1
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] Assuming drive cache:
write through
Oct 8 02:35:04 (none) kernel: sd 3:0:0:0: [sdc] Attached SCSI removabl=
e disk
Oct 8 02:35:04 (none) kernel: floppy0: no floppy controllers found
Oct 8 02:35:04 (none) kernel: device-mapper: uevent: version 1.0.3
Oct 8 02:35:04 (none) kernel: device-mapper: ioctl: 4.17.0-ioctl
(2010-03-05) initialised: dm-devel@redhat.com
Oct 8 02:35:04 (none) kernel: Btrfs loaded
Oct 8 02:35:04 (none) kernel: device label root devid 1 transid 62826 =
/dev/sda2
Oct 8 02:35:04 (none) kernel: loop: module loaded
Oct 8 02:35:04 (none) kernel: NET: Registered protocol family 10
Oct 8 02:35:04 (none) kernel: lo: Disabled Privacy Extensions
Oct 8 02:36:42 (none) kernel: device label root devid 1 transid 62826 =
/dev/sda2
Oct 8 02:38:01 (none) kernel: ATL1E 0000:02:00.0: irq 44 for MSI/MSI-X
Oct 8 02:38:01 (none) kernel: ATL1E 0000:02:00.0: eth0: NIC Link is
Up <100 Mbps Full Duplex>
Oct 8 02:38:01 (none) kernel: ADDRCONF(NETDEV_UP): eth0: link is not r=
eady
Oct 8 02:38:01 (none) kernel: ADDRCONF(NETDEV_CHANGE): eth0: link beco=
mes ready
Oct 8 02:38:12 (none) kernel: eth0: no IPv6 routers present
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:26 (none) kernel: btrfs: sda2 checksum verify failed on
24630292480 wanted 140000C found 48DE1BDD level 0
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:26 (none) kernel: btrfs: sda2 checksum verify failed on
24630292480 wanted 140000C found 48DE1BDD level 0
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:26 (none) kernel: btrfs: sda2 checksum verify failed on
24630292480 wanted 140000C found 48DE1BDD level 0
Oct 8 02:38:26 (none) kernel: btrfs bad tree block start 24630358016
24630292480
Oct 8 02:38:27 (none) kernel: ata1.00: exception Emask 0x0 SAct 0x0
SErr 0x0 action 0x0
Oct 8 02:38:27 (none) kernel: ata1.00: BMDMA stat 0x24
Oct 8 02:38:27 (none) kernel: ata1.00: failed command: READ DMA
Oct 8 02:38:27 (none) kernel: ata1.00: cmd
c8/00:08:7c:3b:41/00:00:00:00:00/e3 tag 0 dma 4096 in
Oct 8 02:38:27 (none) kernel: res 51/40:08:7c:3b:41/00:00:00:00:00/e3
Emask 0x9 (media error)
Oct 8 02:38:27 (none) kernel: ata1.00: status: { DRDY ERR }
Oct 8 02:38:27 (none) kernel: ata1.00: error: { UNC }
Oct 8 02:38:32 (none) kernel: ata1.00: qc timeout (cmd 0xef)
Oct 8 02:38:32 (none) kernel: ata1.00: failed to set xfermode (err_mas=
k=3D0x4)
Oct 8 02:38:37 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:38:42 (none) kernel: ata1: device not ready (errno=3D-16),
forcing hardreset
Oct 8 02:38:42 (none) kernel: ata1: soft resetting link
Oct 8 02:38:47 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:38:52 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:38:52 (none) kernel: ata1: soft resetting link
Oct 8 02:38:57 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:39:02 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:39:02 (none) kernel: ata1: soft resetting link
Oct 8 02:39:07 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:39:37 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:39:37 (none) kernel: ata1: soft resetting link
Oct 8 02:39:42 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:39:42 (none) kernel: ata1: reset failed, giving up
Oct 8 02:39:42 (none) kernel: ata1.00: disabled
Oct 8 02:39:47 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:39:52 (none) kernel: ata1: device not ready (errno=3D-16),
forcing hardreset
Oct 8 02:39:52 (none) kernel: ata1: soft resetting link
Oct 8 02:39:58 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:40:02 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:40:02 (none) kernel: ata1: soft resetting link
Oct 8 02:40:08 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:40:12 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:40:12 (none) kernel: ata1: soft resetting link
Oct 8 02:40:18 (none) kernel: ata1: link is slow to respond, please
be patient (ready=3D0)
Oct 8 02:40:43 (none) kernel: INFO: task ata_aux:633 blocked for more
than 120 seconds.
Oct 8 02:40:43 (none) kernel: "echo 0 >
/proc/sys/kernel/hung_task_timeout_secs" disables this message.
Oct 8 02:40:43 (none) kernel: ata_aux D f06f9cc4 0 633
2 0x00000000
Oct 8 02:40:43 (none) kernel: f06f9cd4 00000046 00000002 f06f9cc4
c10eaadd 00000046 00000046 c12f2680
Oct 8 02:40:43 (none) kernel: c4808140 c1180ee6 c1487140 c1487140
c1487140 f07226d0 c1487140 00000000
Oct 8 02:40:43 (none) kernel: c1182eb0 c1487140 f07226d0 00000001
00000000 7fffffff f06f9d94 f06f9d38
Oct 8 02:40:43 (none) kernel: Call Trace:
Oct 8 02:40:43 (none) kernel: [<c10eaadd>] ? kmem_cache_alloc+0x8d/0x1=
10
Oct 8 02:40:43 (none) kernel: [<c1180ee6>] ?
cfq_init_prio_data.clone.99+0x66/0x120
Oct 8 02:40:43 (none) kernel: [<c1182eb0>] ? cfq_get_queue+0x460/0x590
Oct 8 02:40:43 (none) kernel: [<c12e730d>] schedule_timeout+0x18d/0x2b=
0
Oct 8 02:40:43 (none) kernel: [<c11850fd>] ? kobject_put+0x1d/0x50
Oct 8 02:40:43 (none) kernel: [<c121b1bf>] ? put_device+0xf/0x20
Oct 8 02:40:43 (none) kernel: [<c12e6696>] wait_for_common+0x96/0x120
Oct 8 02:40:43 (none) kernel: [<c103df80>] ? default_wake_function+0x0=
/0x10
Oct 8 02:40:43 (none) kernel: [<c12e67c2>] wait_for_completion+0x12/0x=
20
Oct 8 02:40:43 (none) kernel: [<c1176448>] blk_execute_rq+0x78/0xd0
Oct 8 02:40:43 (none) kernel: [<c1176310>] ? blk_end_sync_rq+0x0/0x30
Oct 8 02:40:43 (none) kernel: [<c117295d>] ? get_request_wait+0x1d/0x1=
90
Oct 8 02:40:43 (none) kernel: [<c103570d>] ?
wakeup_preempt_entity.clone.94+0x8d/0xa0
Oct 8 02:40:43 (none) kernel: [<c1172b2b>] ? blk_get_request+0x5b/0x80
Oct 8 02:40:43 (none) kernel: [<f84318b7>] scsi_execute+0xc7/0x110 [sc=
si_mod]
Oct 8 02:40:43 (none) kernel: [<f8431985>]
scsi_execute_req+0x85/0x160 [scsi_mod]
Oct 8 02:40:43 (none) kernel: [<f84f11a0>]
sd_revalidate_disk+0x100/0x1cb0 [sd_mod]
Oct 8 02:40:43 (none) kernel: [<c1185242>] ? kobject_get+0x12/0x20
Oct 8 02:40:43 (none) kernel: [<c111faf4>] revalidate_disk+0x24/0x70
Oct 8 02:40:43 (none) kernel: [<c12e7f88>] ? mutex_unlock+0x8/0x10
Oct 8 02:40:43 (none) kernel: [<f84efc8a>] sd_rescan+0x1a/0x30 [sd_mod=
]
Oct 8 02:40:43 (none) kernel: [<f84338b4>]
scsi_rescan_device+0x74/0x100 [scsi_mod]
Oct 8 02:40:43 (none) kernel: [<c121b193>] ? get_device+0x13/0x20
Oct 8 02:40:43 (none) kernel: [<f84922dc>]
ata_scsi_dev_rescan+0x8c/0xe0 [libata]
Oct 8 02:40:43 (none) kernel: [<f8492250>] ?
ata_scsi_dev_rescan+0x0/0xe0 [libata]
Oct 8 02:40:43 (none) kernel: [<c105abc0>] worker_thread+0x110/0x250
Oct 8 02:40:43 (none) kernel: [<c102f0b0>] ? __wake_up_common+0x40/0x7=
0
Oct 8 02:40:43 (none) kernel: [<c105eb30>] ? autoremove_wake_function+=
0x0/0x40
Oct 8 02:40:43 (none) kernel: [<c105aab0>] ? worker_thread+0x0/0x250
Oct 8 02:40:43 (none) kernel: [<c105e71c>] kthread+0x6c/0x80
Oct 8 02:40:43 (none) kernel: [<c105e6b0>] ? kthread+0x0/0x80
Oct 8 02:40:43 (none) kernel: [<c1003d3e>] kernel_thread_helper+0x6/0x=
18
Oct 8 02:40:43 (none) kernel: INFO: task tar:1323 blocked for more
than 120 seconds.
Oct 8 02:40:43 (none) kernel: "echo 0 >
/proc/sys/kernel/hung_task_timeout_secs" disables this message.
Oct 8 02:40:43 (none) kernel: tar D c3059b24 0 1323
1258 0x00000004
Oct 8 02:40:43 (none) kernel: c3059b34 00000082 00000002 c3059b24
c3898000 f706a000 c4382a00 c12f2680
Oct 8 02:40:43 (none) kernel: c4a08140 c10682af c1487140 c1487140
c1487140 f066af70 c1487140 00000000
Oct 8 02:40:43 (none) kernel: 00443c53 c1487140 f066af70 00000001
f066af70 c4a08140 c3059b7c c3059b44
Oct 8 02:40:43 (none) kernel: Call Trace:
Oct 8 02:40:43 (none) kernel: [<c10682af>] ? ktime_get_ts+0xff/0x130
Oct 8 02:40:43 (none) kernel: [<c12e6f1c>] io_schedule+0x5c/0xa0
Oct 8 02:40:43 (none) kernel: [<c10bd825>] sync_page+0x35/0x40
Oct 8 02:40:43 (none) kernel: [<c12e75d5>] __wait_on_bit+0x45/0x70
Oct 8 02:40:43 (none) kernel: [<c10bd7f0>] ? sync_page+0x0/0x40
Oct 8 02:40:43 (none) kernel: [<c10bda76>] wait_on_page_bit+0x86/0x90
Oct 8 02:40:43 (none) kernel: [<c105eb70>] ? wake_bit_function+0x0/0x6=
0
Oct 8 02:40:43 (none) kernel: [<f89bde39>]
read_extent_buffer_pages+0x489/0x4c0 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f8994c2b>]
btree_read_extent_buffer_pages.clone.60+0x4b/0xb0 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f89939d0>] ? btree_get_extent+0x0/0x1c=
0 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f89959b7>] read_tree_block+0x47/0x60 [=
btrfs]
Oct 8 02:40:43 (none) kernel: [<f897e185>]
read_block_for_search.clone.38+0xe5/0x330 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f8980656>]
btrfs_search_slot+0x1f6/0x670 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f89b361f>] ?
btrfs_dir_name_len+0xdf/0xf0 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f8993416>] btrfs_lookup_inode+0x36/0xb=
0 [btrfs]
Oct 8 02:40:43 (none) kernel: [<c110b83a>] ? iget5_locked+0x16a/0x190
Oct 8 02:40:43 (none) kernel: [<f89a37ec>] btrfs_iget+0xdc/0x420 [btrf=
s]
Oct 8 02:40:43 (none) kernel: [<f89a3fce>]
btrfs_lookup_dentry+0x1de/0x430 [btrfs]
Oct 8 02:40:43 (none) kernel: [<f89a422b>] btrfs_lookup+0xb/0x20 [btrf=
s]
Oct 8 02:40:43 (none) kernel: [<c10ffc1b>] do_lookup+0x15b/0x1c0
Oct 8 02:40:43 (none) kernel: [<c110183d>] link_path_walk+0x42d/0x920
Oct 8 02:40:43 (none) kernel: [<c1101e34>] path_walk+0x44/0xa0
Oct 8 02:40:43 (none) kernel: [<c1101f91>] do_path_lookup+0x51/0x90
Oct 8 02:40:43 (none) kernel: [<c110230c>] user_path_at+0x3c/0x70
Oct 8 02:40:43 (none) kernel: [<c118d8ae>] ? copy_to_user+0x2e/0x50
Oct 8 02:40:43 (none) kernel: [<c10fac85>] vfs_fstatat+0x35/0x80
Oct 8 02:40:43 (none) kernel: [<c1183b50>] ? _atomic_dec_and_lock+0x50=
/0x70
Oct 8 02:40:43 (none) kernel: [<c10faceb>] vfs_lstat+0x1b/0x20
Oct 8 02:40:43 (none) kernel: [<c10faf94>] sys_lstat64+0x14/0x30
Oct 8 02:40:43 (none) kernel: [<c10f4ef9>] ? filp_close+0x49/0x70
Oct 8 02:40:43 (none) kernel: [<c10f4f8f>] ? sys_close+0x6f/0xc0
Oct 8 02:40:43 (none) kernel: [<c100379f>] sysenter_do_call+0x12/0x28
Oct 8 02:40:47 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:40:47 (none) kernel: ata1: soft resetting link
Oct 8 02:40:52 (none) kernel: ata1: SRST failed (errno=3D-16)
Oct 8 02:40:52 (none) kernel: ata1: reset failed, giving up
Oct 8 02:40:52 (none) kernel: ata1: EH complete
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Unhandled error code
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Result: hostbyte=3D0x0=
4
driverbyte=3D0x00
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] CDB: cdb[0]=3D0x28: 28
00 03 41 3b 7c 00 00 08 00
Oct 8 02:40:52 (none) kernel: end_request: I/O error, dev sda, sector =
54606716
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Unhandled error code
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Result: hostbyte=3D0x0=
4
driverbyte=3D0x00
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] CDB: cdb[0]=3D0x28: 28
00 03 3d 83 74 00 00 08 00
Oct 8 02:40:52 (none) kernel: end_request: I/O error, dev sda, sector =
54362996
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] READ CAPACITY(16) fail=
ed
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Result: hostbyte=3D0x0=
4
driverbyte=3D0x00
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Sense not available.
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] READ CAPACITY failed
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Result: hostbyte=3D0x0=
4
driverbyte=3D0x00
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Sense not available.
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Asking for cache data =
failed
Oct 8 02:40:52 (none) kernel: sd 0:0:0:0: [sda] Assuming drive cache:
write through
Oct 8 02:40:52 (none) kernel: sda: detected capacity change from
32296140800 to 0
Oct 8 02:40:52 (none) kernel: ------------[ cut here ]------------
Oct 8 02:40:52 (none) kernel: WARNING: at fs/btrfs/extent_io.c:3690
copy_extent_buffer+0x117/0x150 [btrfs]()
Oct 8 02:40:52 (none) kernel: Hardware name: S101
Oct 8 02:40:52 (none) kernel: Modules linked in: ipv6 loop btrfs
zlib_deflate crc32c libcrc32c dm_crypt md_mod dm_mirror dm_region_hash
dm_log dm_mod usb_storage uhci_hcd ehci_hcd usbcore arc4 ecb ath9k
ath9k_common ath9k_hw ath mac80211 cfg80211 sg sd_mod atl1e ata_piix
libata scsi_mod snd_hda_codec_realtek snd_hda_intel snd_hda_codec
snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device
snd_hwdep snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss
snd soundcore rtc_cmos rtc_core rtc_lib eeepc_laptop rfkill
pci_hotplug led_class sparse_keymap pcspkr intel_agp agpgart video
output thermal processor button battery ac
Oct 8 02:40:52 (none) kernel: Pid: 1291, comm: btrfs-transacti Not
tainted 2.6.35-ARCH #1
Oct 8 02:40:52 (none) kernel: Call Trace:
Oct 8 02:40:52 (none) kernel: [<c10439bd>] warn_slowpath_common+0x6d/0=
xa0
Oct 8 02:40:52 (none) kernel: [<f89be7e7>] ?
copy_extent_buffer+0x117/0x150 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89be7e7>] ?
copy_extent_buffer+0x117/0x150 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c1043a0d>] warn_slowpath_null+0x1d/0x2=
0
Oct 8 02:40:52 (none) kernel: [<f89be7e7>]
copy_extent_buffer+0x117/0x150 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f897e91d>] __push_leaf_left+0x18d/0x6d=
0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f897e745>] ?
btrfs_leaf_free_space+0x45/0x90 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f897ef83>] push_leaf_left+0x123/0x130 =
[btrfs]
Oct 8 02:40:52 (none) kernel: [<f898013a>] split_leaf+0x5fa/0x700 [btr=
fs]
Oct 8 02:40:52 (none) kernel: [<f897a355>] ? leaf_space_used+0x85/0xb0=
[btrfs]
Oct 8 02:40:52 (none) kernel: [<f897e745>] ?
btrfs_leaf_free_space+0x45/0x90 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89c9e4d>] ?
btrfs_set_lock_blocking+0x1d/0x30 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f8980a4f>]
btrfs_search_slot+0x5ef/0x670 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89817d3>]
btrfs_insert_empty_items+0x53/0xa0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898bb06>]
run_clustered_refs+0x626/0x8c0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89d4c01>] ?
btrfs_find_ref_cluster+0x1/0x1a0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898be47>]
btrfs_run_delayed_refs+0xa7/0x1c0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89b706b>] ?
btrfs_run_ordered_operations+0x1db/0x1f0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89996f4>]
btrfs_commit_transaction+0x64/0x6f0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c105eb30>] ? autoremove_wake_function+=
0x0/0x40
Oct 8 02:40:52 (none) kernel: [<f899443f>]
transaction_kthread+0x20f/0x230 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f8994230>] ?
transaction_kthread+0x0/0x230 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c105e71c>] kthread+0x6c/0x80
Oct 8 02:40:52 (none) kernel: [<c105e6b0>] ? kthread+0x0/0x80
Oct 8 02:40:52 (none) kernel: [<c1003d3e>] kernel_thread_helper+0x6/0x=
18
Oct 8 02:40:52 (none) kernel: ---[ end trace 8b4894fc857a26c6 ]---
Oct 8 02:40:52 (none) kernel: ------------[ cut here ]------------
Oct 8 02:40:52 (none) kernel: WARNING: at fs/btrfs/extent_io.c:3690
copy_extent_buffer+0x117/0x150 [btrfs]()
Oct 8 02:40:52 (none) kernel: Hardware name: S101
Oct 8 02:40:52 (none) kernel: Modules linked in: ipv6 loop btrfs
zlib_deflate crc32c libcrc32c dm_crypt md_mod dm_mirror dm_region_hash
dm_log dm_mod usb_storage uhci_hcd ehci_hcd usbcore arc4 ecb ath9k
ath9k_common ath9k_hw ath mac80211 cfg80211 sg sd_mod atl1e ata_piix
libata scsi_mod snd_hda_codec_realtek snd_hda_intel snd_hda_codec
snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device
snd_hwdep snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss
snd soundcore rtc_cmos rtc_core rtc_lib eeepc_laptop rfkill
pci_hotplug led_class sparse_keymap pcspkr intel_agp agpgart video
output thermal processor button battery ac
Oct 8 02:40:52 (none) kernel: Pid: 1291, comm: btrfs-transacti
Tainted: G W 2.6.35-ARCH #1
Oct 8 02:40:52 (none) kernel: Call Trace:
Oct 8 02:40:52 (none) kernel: [<c10439bd>] warn_slowpath_common+0x6d/0=
xa0
Oct 8 02:40:52 (none) kernel: [<f89be7e7>] ?
copy_extent_buffer+0x117/0x150 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89be7e7>] ?
copy_extent_buffer+0x117/0x150 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c1043a0d>] warn_slowpath_null+0x1d/0x2=
0
Oct 8 02:40:52 (none) kernel: [<f89be7e7>]
copy_extent_buffer+0x117/0x150 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f897e9a1>] __push_leaf_left+0x211/0x6d=
0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f897ef83>] push_leaf_left+0x123/0x130 =
[btrfs]
Oct 8 02:40:52 (none) kernel: [<f898013a>] split_leaf+0x5fa/0x700 [btr=
fs]
Oct 8 02:40:52 (none) kernel: [<f897a355>] ? leaf_space_used+0x85/0xb0=
[btrfs]
Oct 8 02:40:52 (none) kernel: [<f897e745>] ?
btrfs_leaf_free_space+0x45/0x90 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89c9e4d>] ?
btrfs_set_lock_blocking+0x1d/0x30 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f8980a4f>]
btrfs_search_slot+0x5ef/0x670 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89817d3>]
btrfs_insert_empty_items+0x53/0xa0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898bb06>]
run_clustered_refs+0x626/0x8c0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89d4c01>] ?
btrfs_find_ref_cluster+0x1/0x1a0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898be47>]
btrfs_run_delayed_refs+0xa7/0x1c0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89b706b>] ?
btrfs_run_ordered_operations+0x1db/0x1f0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89996f4>]
btrfs_commit_transaction+0x64/0x6f0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c105eb30>] ? autoremove_wake_function+=
0x0/0x40
Oct 8 02:40:52 (none) kernel: [<f899443f>]
transaction_kthread+0x20f/0x230 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f8994230>] ?
transaction_kthread+0x0/0x230 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c105e71c>] kthread+0x6c/0x80
Oct 8 02:40:52 (none) kernel: [<c105e6b0>] ? kthread+0x0/0x80
Oct 8 02:40:52 (none) kernel: [<c1003d3e>] kernel_thread_helper+0x6/0x=
18
Oct 8 02:40:52 (none) kernel: ---[ end trace 8b4894fc857a26c7 ]---
Oct 8 02:40:52 (none) kernel: ------------[ cut here ]------------
Oct 8 02:40:52 (none) kernel: kernel BUG at fs/btrfs/ctree.c:2628!
Oct 8 02:40:52 (none) kernel: invalid opcode: 0000 [#1] PREEMPT SMP
Oct 8 02:40:52 (none) kernel: last sysfs file:
/sys/devices/virtual/bdi/btrfs-1/uevent
Oct 8 02:40:52 (none) kernel: Modules linked in: ipv6 loop btrfs
zlib_deflate crc32c libcrc32c dm_crypt md_mod dm_mirror dm_region_hash
dm_log dm_mod usb_storage uhci_hcd ehci_hcd usbcore arc4 ecb ath9k
ath9k_common ath9k_hw ath mac80211 cfg80211 sg sd_mod atl1e ata_piix
libata scsi_mod snd_hda_codec_realtek snd_hda_intel snd_hda_codec
snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device
snd_hwdep snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss
snd soundcore rtc_cmos rtc_core rtc_lib eeepc_laptop rfkill
pci_hotplug led_class sparse_keymap pcspkr intel_agp agpgart video
output thermal processor button battery ac
Oct 8 02:40:52 (none) kernel:
Oct 8 02:40:52 (none) kernel: Pid: 1291, comm: btrfs-transacti
Tainted: G W 2.6.35-ARCH #1 S101/S101
Oct 8 02:40:52 (none) kernel: EIP: 0060:[<f897ee50>] EFLAGS: 00010246 =
CPU: 0
Oct 8 02:40:52 (none) kernel: EIP is at __push_leaf_left+0x6c0/0x6d0 [=
btrfs]
Oct 8 02:40:52 (none) kernel: EAX: c373a000 EBX: 00000010 ECX:
c148eedc EDX: 00000000
Oct 8 02:40:52 (none) kernel: ESI: 00000000 EDI: c2cd3f00 EBP:
c373bcf8 ESP: c373bc88
Oct 8 02:40:52 (none) kernel: DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: =
0068
Oct 8 02:40:52 (none) kernel: Process btrfs-transacti (pid: 1291,
ti=3Dc373a000 task=3Df0720cf0 task.ti=3Dc373a000)
Oct 8 02:40:52 (none) kernel: Stack:
Oct 8 02:40:52 (none) kernel: 00000cf6 0000030a c2cd3f14 c2cd3f18
00000004 c373bcac f376d270 c2cd3f0c
Oct 8 02:40:52 (none) kernel: <0> c2cd3f10 c2cd3f14 c2cd3f18 fffff000
f707e000 00000190 000001dc 00000f9b
Oct 8 02:40:52 (none) kernel: <0> 00000000 f376ea80 00000cf6 0000030a
00000000 0000f56b 00000000 f707e000
Oct 8 02:40:52 (none) kernel: Call Trace:
Oct 8 02:40:52 (none) kernel: [<f897ef83>] ? push_leaf_left+0x123/0x13=
0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898013a>] ? split_leaf+0x5fa/0x700 [b=
trfs]
Oct 8 02:40:52 (none) kernel: [<f897a355>] ? leaf_space_used+0x85/0xb0=
[btrfs]
Oct 8 02:40:52 (none) kernel: [<f897e745>] ?
btrfs_leaf_free_space+0x45/0x90 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89c9e4d>] ?
btrfs_set_lock_blocking+0x1d/0x30 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f8980a4f>] ?
btrfs_search_slot+0x5ef/0x670 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89817d3>] ?
btrfs_insert_empty_items+0x53/0xa0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898bb06>] ?
run_clustered_refs+0x626/0x8c0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89d4c01>] ?
btrfs_find_ref_cluster+0x1/0x1a0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f898be47>] ?
btrfs_run_delayed_refs+0xa7/0x1c0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89b706b>] ?
btrfs_run_ordered_operations+0x1db/0x1f0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f89996f4>] ?
btrfs_commit_transaction+0x64/0x6f0 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c105eb30>] ? autoremove_wake_function+=
0x0/0x40
Oct 8 02:40:52 (none) kernel: [<f899443f>] ?
transaction_kthread+0x20f/0x230 [btrfs]
Oct 8 02:40:52 (none) kernel: [<f8994230>] ?
transaction_kthread+0x0/0x230 [btrfs]
Oct 8 02:40:52 (none) kernel: [<c105e71c>] ? kthread+0x6c/0x80
Oct 8 02:40:52 (none) kernel: [<c105e6b0>] ? kthread+0x0/0x80
Oct 8 02:40:52 (none) kernel: [<c1003d3e>] ? kernel_thread_helper+0x6/=
0x18
Oct 8 02:40:52 (none) kernel: Code: 18 89 5c 24 04 c7 04 24 03 da 9d
f8 89 44 24 08 e8 8b 76 96 c8 ba 61 0a 00 00 b8 d6 d9 9d f8 e8 a7 4b
6c c8 e9 68 fc ff ff 0f 0b <0f> 0b 8d b4 26 00 00 00 00 8d bc 27 00 00
00 00 55 89 e5 83 ec
Oct 8 02:40:52 (none) kernel: EIP: [<f897ee50>]
__push_leaf_left+0x6c0/0x6d0 [btrfs] SS:ESP 0068:c373bc88
Oct 8 02:40:52 (none) kernel: ---[ end trace 8b4894fc857a26c8 ]---
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" =
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* linux-next: manual merge of the alacrity tree with Linus' and other trees
From: Stephen Rothwell @ 2010-10-08 3:03 UTC (permalink / raw)
To: Gregory Haskins; +Cc: linux-next, linux-kernel
Hi Gregory,
Today's linux-next merge of the alacrity tree got a conflict in
include/linux/Kbuild between various commits from Linus' and other trees
and various commits from the alacrity tree.
I fixed it up (see below) and can carry the fix as necessary. The main
problem is commit 60641aa1f379820e99ac7f45a38b43795670c741 ("include:
replace unifdef-y with header-y") from Linus' tree.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --cc include/linux/Kbuild
index 3c44beb,1a31099..0000000
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@@ -125,105 -70,43 +125,106 @@@ header-y += fd.
header-y += fdreg.h
header-y += fib_rules.h
header-y += fiemap.h
+header-y += filter.h
header-y += firewire-cdev.h
header-y += firewire-constants.h
+header-y += flat.h
+header-y += fs.h
header-y += fuse.h
-header-y += genetlink.h
+header-y += futex.h
+header-y += gameport.h
header-y += gen_stats.h
+header-y += generic_serial.h
+header-y += genetlink.h
header-y += gfs2_ondisk.h
header-y += gigaset_dev.h
+header-y += hdlc.h
+header-y += hdlcdrv.h
+header-y += hdreg.h
+header-y += hid.h
+header-y += hiddev.h
+header-y += hidraw.h
+header-y += hpet.h
header-y += hysdn_if.h
+header-y += i2c-dev.h
+header-y += i2c.h
header-y += i2o-dev.h
header-y += i8k.h
+header-y += icmp.h
+header-y += icmpv6.h
+header-y += if.h
+header-y += if_addr.h
header-y += if_addrlabel.h
header-y += if_arcnet.h
+header-y += if_arp.h
header-y += if_bonding.h
+header-y += if_bridge.h
header-y += if_cablemodem.h
+header-y += if_ec.h
+header-y += if_eql.h
+header-y += if_ether.h
header-y += if_fc.h
-header-y += if.h
+header-y += if_fddi.h
+header-y += if_frad.h
header-y += if_hippi.h
header-y += if_infiniband.h
+header-y += if_link.h
+header-y += if_ltalk.h
header-y += if_packet.h
+header-y += if_phonet.h
header-y += if_plip.h
header-y += if_ppp.h
+header-y += if_pppol2tp.h
+header-y += if_pppox.h
header-y += if_slip.h
header-y += if_strip.h
+header-y += if_tr.h
header-y += if_tun.h
+header-y += if_tunnel.h
+header-y += if_vlan.h
+header-y += if_x25.h
+header-y += igmp.h
+header-y += in.h
+header-y += in6.h
header-y += in_route.h
+header-y += inet_diag.h
+header-y += inotify.h
+header-y += input.h
++header-y += ioq.h
header-y += ioctl.h
+header-y += ip.h
header-y += ip6_tunnel.h
+header-y += ip_vs.h
+header-y += ipc.h
+header-y += ipmi.h
header-y += ipmi_msgdefs.h
header-y += ipsec.h
-header-y += ip_vs.h
+header-y += ipv6.h
+header-y += ipv6_route.h
header-y += ipx.h
header-y += irda.h
+header-y += irqnr.h
+header-y += isdn.h
+header-y += isdn_divertif.h
+header-y += isdn_ppp.h
+header-y += isdnif.h
header-y += iso_fs.h
+header-y += ivtv.h
+header-y += ivtvfb.h
header-y += ixjuser.h
header-y += jffs2.h
+header-y += joystick.h
+header-y += kd.h
+header-y += kdev_t.h
+header-y += kernel.h
+header-y += kernelcapi.h
+header-y += keyboard.h
header-y += keyctl.h
+header-y += l2tp.h
header-y += limits.h
+header-y += llc.h
+header-y += loop.h
+header-y += lp.h
header-y += magic.h
header-y += major.h
header-y += map_to_7segment.h
@@@ -286,109 -136,259 +287,112 @@@ header-y += phantom.
header-y += phonet.h
header-y += pkt_cls.h
header-y += pkt_sched.h
+header-y += pktcdvd.h
+header-y += pmu.h
+header-y += poll.h
header-y += posix_types.h
header-y += ppdev.h
+header-y += ppp-comp.h
+header-y += ppp_defs.h
+header-y += pps.h
header-y += prctl.h
-header-y += qnxtypes.h
+header-y += ptrace.h
header-y += qnx4_fs.h
+header-y += qnxtypes.h
+header-y += quota.h
header-y += radeonfb.h
+header-y += random.h
header-y += raw.h
+header-y += rds.h
+header-y += reboot.h
+header-y += reiserfs_fs.h
+header-y += reiserfs_xattr.h
header-y += resource.h
+header-y += rfkill.h
header-y += romfs_fs.h
header-y += rose.h
+header-y += route.h
+header-y += rtc.h
+header-y += rtnetlink.h
+header-y += scc.h
+header-y += sched.h
+header-y += screen_info.h
+header-y += sdla.h
+header-y += securebits.h
+header-y += selinux_netlink.h
+header-y += sem.h
+header-y += serial.h
+header-y += serial_core.h
header-y += serial_reg.h
+header-y += serio.h
+header-y += shm.h
++header-y += shm_signal.h
+header-y += signal.h
+header-y += signalfd.h
+header-y += smb.h
+header-y += smb_fs.h
+header-y += smb_mount.h
header-y += smbno.h
header-y += snmp.h
+header-y += socket.h
header-y += sockios.h
header-y += som.h
+header-y += sonet.h
+header-y += sonypi.h
header-y += sound.h
+header-y += soundcard.h
+header-y += stat.h
+header-y += stddef.h
+header-y += string.h
header-y += suspend_ioctls.h
+header-y += swab.h
+header-y += synclink.h
+header-y += sysctl.h
header-y += taskstats.h
+header-y += tcp.h
header-y += telephony.h
header-y += termios.h
+header-y += time.h
header-y += times.h
+header-y += timex.h
header-y += tiocl.h
header-y += tipc.h
header-y += tipc_config.h
header-y += toshiba.h
+header-y += tty.h
+header-y += types.h
header-y += udf_fs_i.h
+header-y += udp.h
+header-y += uinput.h
+header-y += uio.h
header-y += ultrasound.h
header-y += un.h
+header-y += unistd.h
+header-y += usbdevice_fs.h
header-y += utime.h
+header-y += utsname.h
header-y += veth.h
-header-y += videotext.h
-header-y += x25.h
-
-unifdef-y += acct.h
-unifdef-y += adb.h
-unifdef-y += adfs_fs.h
-unifdef-y += agpgart.h
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \
- $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
-unifdef-y += a.out.h
-endif
-unifdef-y += apm_bios.h
-unifdef-y += atalk.h
-unifdef-y += atmdev.h
-unifdef-y += atm.h
-unifdef-y += atm_tcp.h
-unifdef-y += audit.h
-unifdef-y += auto_fs.h
-unifdef-y += auxvec.h
-unifdef-y += binfmts.h
-unifdef-y += blktrace_api.h
-unifdef-y += capability.h
-unifdef-y += capi.h
-unifdef-y += cciss_ioctl.h
-unifdef-y += cdrom.h
-unifdef-y += cm4000_cs.h
-unifdef-y += cn_proc.h
-unifdef-y += coda.h
-unifdef-y += connector.h
-unifdef-y += cuda.h
-unifdef-y += cyclades.h
-unifdef-y += dccp.h
-unifdef-y += dlm.h
-unifdef-y += dlm_plock.h
-unifdef-y += edd.h
-unifdef-y += elf.h
-unifdef-y += elfcore.h
-unifdef-y += errno.h
-unifdef-y += errqueue.h
-unifdef-y += ethtool.h
-unifdef-y += eventpoll.h
-unifdef-y += signalfd.h
-unifdef-y += ext2_fs.h
-unifdef-y += fb.h
-unifdef-y += fcntl.h
-unifdef-y += filter.h
-unifdef-y += flat.h
-unifdef-y += futex.h
-unifdef-y += fs.h
-unifdef-y += gameport.h
-unifdef-y += generic_serial.h
-unifdef-y += hdlcdrv.h
-unifdef-y += hdlc.h
-unifdef-y += hdreg.h
-unifdef-y += hid.h
-unifdef-y += hiddev.h
-unifdef-y += hidraw.h
-unifdef-y += hpet.h
-unifdef-y += i2c.h
-unifdef-y += i2c-dev.h
-unifdef-y += icmp.h
-unifdef-y += icmpv6.h
-unifdef-y += if_addr.h
-unifdef-y += if_arp.h
-unifdef-y += if_bridge.h
-unifdef-y += if_ec.h
-unifdef-y += if_eql.h
-unifdef-y += if_ether.h
-unifdef-y += if_fddi.h
-unifdef-y += if_frad.h
-unifdef-y += if_ltalk.h
-unifdef-y += if_link.h
-unifdef-y += if_phonet.h
-unifdef-y += if_pppol2tp.h
-unifdef-y += if_pppox.h
-unifdef-y += if_tr.h
-unifdef-y += if_tunnel.h
-unifdef-y += if_vlan.h
-unifdef-y += igmp.h
-unifdef-y += inet_diag.h
-unifdef-y += in.h
-unifdef-y += in6.h
-unifdef-y += inotify.h
-unifdef-y += input.h
-unifdef-y += ioq.h
-unifdef-y += ip.h
-unifdef-y += ipc.h
-unifdef-y += ipmi.h
-unifdef-y += ipv6.h
-unifdef-y += ipv6_route.h
-unifdef-y += isdn.h
-unifdef-y += isdnif.h
-unifdef-y += isdn_divertif.h
-unifdef-y += isdn_ppp.h
-unifdef-y += ivtv.h
-unifdef-y += ivtvfb.h
-unifdef-y += joystick.h
-unifdef-y += kdev_t.h
-unifdef-y += kd.h
-unifdef-y += kernelcapi.h
-unifdef-y += kernel.h
-unifdef-y += keyboard.h
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \
- $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
-unifdef-y += kvm.h
-endif
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \
- $(srctree)/include/asm-$(SRCARCH)/kvm_para.h),)
-unifdef-y += kvm_para.h
-endif
-unifdef-y += llc.h
-unifdef-y += loop.h
-unifdef-y += lp.h
-unifdef-y += mempolicy.h
-unifdef-y += mii.h
-unifdef-y += mman.h
-unifdef-y += mroute.h
-unifdef-y += mroute6.h
-unifdef-y += msdos_fs.h
-unifdef-y += msg.h
-unifdef-y += nbd.h
-unifdef-y += ncp_fs.h
-unifdef-y += ncp.h
-unifdef-y += ncp_mount.h
-unifdef-y += netdevice.h
-unifdef-y += netfilter_bridge.h
-unifdef-y += netfilter_decnet.h
-unifdef-y += netfilter.h
-unifdef-y += netfilter_ipv4.h
-unifdef-y += netfilter_ipv6.h
-unifdef-y += net.h
-unifdef-y += netlink.h
-unifdef-y += nfs3.h
-unifdef-y += nfs4.h
-unifdef-y += nfsacl.h
-unifdef-y += nfs_fs.h
-unifdef-y += nfs.h
-unifdef-y += nfs_idmap.h
-unifdef-y += n_r3964.h
-unifdef-y += nubus.h
-unifdef-y += nvram.h
-unifdef-y += oom.h
-unifdef-y += parport.h
-unifdef-y += patchkey.h
-unifdef-y += pci.h
-unifdef-y += personality.h
-unifdef-y += pktcdvd.h
-unifdef-y += pmu.h
-unifdef-y += poll.h
-unifdef-y += ppp_defs.h
-unifdef-y += ppp-comp.h
-unifdef-y += pps.h
-unifdef-y += ptrace.h
-unifdef-y += quota.h
-unifdef-y += random.h
-unifdef-y += rfkill.h
-unifdef-y += irqnr.h
-unifdef-y += reboot.h
-unifdef-y += reiserfs_fs.h
-unifdef-y += reiserfs_xattr.h
-unifdef-y += route.h
-unifdef-y += rtc.h
-unifdef-y += rtnetlink.h
-unifdef-y += scc.h
-unifdef-y += sched.h
-unifdef-y += screen_info.h
-unifdef-y += sdla.h
-unifdef-y += securebits.h
-unifdef-y += selinux_netlink.h
-unifdef-y += sem.h
-unifdef-y += serial_core.h
-unifdef-y += serial.h
-unifdef-y += serio.h
-unifdef-y += shm.h
-unifdef-y += shm_signal.h
-unifdef-y += signal.h
-unifdef-y += smb_fs.h
-unifdef-y += smb.h
-unifdef-y += smb_mount.h
-unifdef-y += socket.h
-unifdef-y += sonet.h
-unifdef-y += sonypi.h
-unifdef-y += soundcard.h
-unifdef-y += stat.h
-unifdef-y += stddef.h
-unifdef-y += string.h
-unifdef-y += swab.h
-unifdef-y += synclink.h
-unifdef-y += sysctl.h
-unifdef-y += tcp.h
-unifdef-y += time.h
-unifdef-y += timex.h
-unifdef-y += tty.h
-unifdef-y += types.h
-unifdef-y += udp.h
-unifdef-y += uinput.h
-unifdef-y += uio.h
-unifdef-y += unistd.h
-unifdef-y += usbdevice_fs.h
-unifdef-y += utsname.h
-unifdef-y += vhost.h
-unifdef-y += vbus_pci.h
-unifdef-y += venet.h
-unifdef-y += videodev2.h
-unifdef-y += videodev.h
-unifdef-y += virtio_config.h
-unifdef-y += virtio_ids.h
-unifdef-y += virtio_blk.h
-unifdef-y += virtio_net.h
-unifdef-y += virtio_9p.h
-unifdef-y += virtio_balloon.h
-unifdef-y += virtio_console.h
-unifdef-y += virtio_pci.h
-unifdef-y += virtio_ring.h
-unifdef-y += virtio_rng.h
-unifdef-y += vt.h
-unifdef-y += wait.h
-unifdef-y += wanrouter.h
-unifdef-y += watchdog.h
-unifdef-y += wireless.h
-unifdef-y += xattr.h
-unifdef-y += xfrm.h
-
-objhdr-y += version.h
+header-y += vhost.h
++header-y += vbus_pci.h
++header-y += venet.h
+header-y += videodev.h
+header-y += videodev2.h
+header-y += virtio_9p.h
+header-y += virtio_balloon.h
+header-y += virtio_blk.h
+header-y += virtio_config.h
+header-y += virtio_console.h
+header-y += virtio_ids.h
+header-y += virtio_net.h
+header-y += virtio_pci.h
+header-y += virtio_ring.h
+header-y += virtio_rng.h
+header-y += vt.h
+header-y += wait.h
+header-y += wanrouter.h
+header-y += watchdog.h
header-y += wimax.h
-header-y += wimax/
+header-y += wireless.h
+header-y += x25.h
+header-y += xattr.h
+header-y += xfrm.h
^ permalink raw reply
* [PATCH v7] power: introduce library for device-specific OPPs
From: Nishanth Menon @ 2010-10-08 3:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <[PATCH] power: introduce library for device-specific OPPs>
SoCs have a standard set of tuples consisting of frequency and
voltage pairs that the device will support per voltage domain. These
are called Operating Performance Points or OPPs. The actual
definitions of OPP varies over silicon versions. For a specific domain,
we can have a set of {frequency, voltage} pairs. As the kernel boots
and more information is available, a default set of these are activated
based on the precise nature of device. Further on operation, based on
conditions prevailing in the system (such as temperature), some OPP
availability may be temporarily controlled by the SoC frameworks.
To implement an OPP, some sort of power management support is necessary
hence this library depends on CONFIG_PM.
Contributions include:
Sanjeev Premi for the initial concept:
http://patchwork.kernel.org/patch/50998/
Kevin Hilman for converting original design to device-based
Kevin Hilman and Paul Walmsey for cleaning up many of the function
abstractions, improvements and data structure handling
Romit Dasgupta for using enums instead of opp pointers
Thara Gopinath, Eduardo Valentin and Vishwanath BS for fixes and
cleanups.
Linus Walleij for recommending this layer be made generic for usage
in other architectures beyond OMAP and ARM.
Mark Brown, Andrew Morton, Rafael J Wysocki, Paul E McKenney for valuable
improvements.
Discussions and comments from:
http://marc.info/?l=linux-omap&m=126033945313269&w=2
http://marc.info/?l=linux-omap&m=125482970102327&w=2
http://marc.info/?t=125809247500002&r=1&w=2
http://marc.info/?l=linux-omap&m=126025973426007&w=2
http://marc.info/?t=128152609200064&r=1&w=2
http://marc.info/?t=128468723000002&r=1&w=2
incorporated.
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Phil Carmody <ext-phil.2.carmody@nokia.com>
Cc: Roberto Granados Dorado <x0095451@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Tero Kristo <Tero.Kristo@nokia.com>
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath BS <vishwanath.bs@ti.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
V7:
removed pr_fmt and used dev_err/warn instead of pr_xx family where
possible
replaced out1 label with unlock to make it readable
Accepted a offline suggestion to use IS_ERR_OR_NULL to replace
!var || IS_ERR(var) check in find_device_opp, opp_get_voltage &
opp_get_freq
V6: https://patchwork.kernel.org/patch/235591/
mutexes reduced to a single one. dev_opp_list_lock now protects
both the devices and the opp lists, doc updated accordingly.
fixed opp_add removed an irrelevant find_device_opp, used IS_ERR to
check pointer
fixed updater routines to remove unnecessary reader operations.
comments from v5 not included in v6:
- synchronize_rcu() is not needed after list_add_rcu as pointed by
Paul in http://marc.info/?l=linux-omap&m=128535708720191&w=2
I have retained it's usage after list_replace_rcu as with v4.
- Temporary release of mutex in opp_add under if (IS_ERR(dev_opp)) {
Rationale:
If two parallel calls to opp_add on the same device node which
is not yet added in the list can cause data structure integrity
issues. For example:
c1: holds mutex dev_opp_list_lock
c2: starts and is blocked on dev_opp_list_lock mutex here
dev_opp = find_device_opp(dev); [c1 in progress here]
if (IS_ERR(dev_opp)) {
If c1 releases dev_opp_list_lock here, c2 can proceed
to call find_device_opp which will return error and will
cause following allocation to take place for same device
node.
dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
This is undesirable as it will result in an additional node added
for the same device (since the device is the same, c1 should have
added the new node and c2 should have just added an opp).
Since the actual addition of a device node by itself is rare,
kzalloc is a tiny penalty to pay for integrity of the data structure.
The other option being to move the kzalloc before the mutex locking,
but, that will cause dev_opp allocation overhead for every opp
addition.
All other comments have been incorporated.
Tested with cpufreq on SDP3630 (TI OMAP3630) with lockdep debugging to
catch races.
V5: https://patchwork.kernel.org/patch/223272/
opp pointers were being passed to callers outside rcu locks, this
causes the pointers to be potentially invalid between calls if
opp_enable/disable calls take place.
The solution for this cannot be reference counters either, as
opp pointer without control of opp library and rcu locks are
completely untrustworthy. The better approach is to enforce
restrictions on callers of query and retrieval functions to wrap
the relevant parts under rcu locks. This allows for tremendous
flexibility in the way opp libraries can be used as the users
can optimize their implementation based on the requirements.
NOTE: find_device_opp is implicitly wrapped as a result.
(ref, v4 comments)
One more side-effect has been that the opp_enable and disable
functions changed their prototypes to make it a little more easier
for the users to use them without having to get the pointers before
hand, as well as do the functionality that is being provided currently
as well.
opp_init_cpufreq_table now returns int and result of operation for
callers to adequately handle their error conditions.
pr_fmt is being used instead of duplicating "%s" .. __func__ with
every pr_xxx call.
Documentation update to reflect these.
Sample usage:
http://pastebin.mozilla.org/802375: cleanups for omap pm layer
http://pastebin.mozilla.org/802374: omap opp initialization
V4: http://marc.info/?t=128533285000002&r=1&w=2
Cc list trimmed to just the MLs.
RCU implementation - thanks for the pointers Rafael
re-tested on OMAP3630 with lock debugging enabled including cpufreq,
idle paths and "exception cases - enable/disable".
available_opp_count removed as it complicated the updates altogether
+ the usage latencies are not too high given small lists.
In removed list_reverse usage as rcu has no list reverse equivalents
+ searching either direction has no real difference when the list
is ordered.
change in protos for get_{voltage,frequency} - const removed from
parameter as rcu_dereference causes build warnings
introduced opp_set_availability helper to wrap common code between
opp_{enable,disable} - leaving these as is as they are more readable
from usage perspective + these are not meant to be used in hot paths
anyways.
Header guard __ASM_OPP_H replaced with __LINUX_OPP_H__ for opp.h
V3: https://patchwork.kernel.org/patch/200382/
Bunch of documentation update based on feedback
removed opp_def - opp_add enables the opp by default
lock usage optimization
Sample usage:
http://pastebin.mozilla.org/794786 -> cleanups for OMAP power
http://pastebin.mozilla.org/794787 -> Sample OPP initialization for OMAP
V2: https://patchwork.kernel.org/patch/189532/
Incorporated review comments from v1. major changes being:
$subject change to reflect this is for power.
Documentation revamp and including it in the patch :)
OPP_DEF removed - lets introduce this if needed or leave it to
SOC frameworks to organize code as needed.
Rename of enable to available to better reflect the intent
few fixes and typos
Introduced mutex based locking for controlling access to list
modification (note: query functions are still unsafe- rationale
in the patch below)
A new home for opp.c in drivers/base/power (moved from lib/)
A few optimization in function flow and additional error checks
added to exposed functions
offline aligned with Kevin for cleaning up the copyrights
V1: http://marc.info/?t=128468723000002&r=1&w=2
Documentation/power/00-INDEX | 2 +
Documentation/power/opp.txt | 373 +++++++++++++++++++++++++
drivers/base/power/Makefile | 1 +
drivers/base/power/opp.c | 626 ++++++++++++++++++++++++++++++++++++++++++
include/linux/opp.h | 105 +++++++
kernel/power/Kconfig | 14 +
6 files changed, 1121 insertions(+), 0 deletions(-)
create mode 100644 Documentation/power/opp.txt
create mode 100644 drivers/base/power/opp.c
create mode 100644 include/linux/opp.h
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index fb742c2..45e9d4a 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -14,6 +14,8 @@ interface.txt
- Power management user interface in /sys/power
notifiers.txt
- Registering suspend notifiers in device drivers
+opp.txt
+ - Operating Performance Point library
pci.txt
- How the PCI Subsystem Does Power Management
pm_qos_interface.txt
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
new file mode 100644
index 0000000..b309e30
--- /dev/null
+++ b/Documentation/power/opp.txt
@@ -0,0 +1,373 @@
+*=============*
+* OPP Library *
+*=============*
+
+Contents
+--------
+1. Introduction
+2. Initial OPP List Registration
+3. OPP Search Functions
+4. OPP Availability Control Functions
+5. OPP Data Retrieval Functions
+6. Cpufreq Table Generation
+7. Data Structures
+
+1. Introduction
+===============
+Complex SoCs of today consists of a multiple sub-modules working in conjunction.
+In an operational system executing varied use cases, not all modules in the SoC
+need to function at their highest performing frequency all the time. To
+facilitate this, sub-modules in a SoC are grouped into domains, allowing some
+domains to run at lower voltage and frequency while other domains are loaded
+more. The set of discrete tuples consisting of frequency and voltage pairs that
+the device will support per domain are called Operating Performance Points or
+OPPs.
+
+OPP library provides a set of helper functions to organize and query the OPP
+information. The library is located in drivers/base/power/opp.c and the header
+is located in include/linux/opp.h. OPP library can be enabled by enabling
+CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
+CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+optionally boot at a certain OPP without needing cpufreq.
+
+Typical usage of the OPP library is as follows:
+(users) -> registers a set of default OPPs -> (library)
+SoC framework -> modifies on required cases certain OPPs -> OPP layer
+ -> queries to search/retrieve information ->
+
+OPP layer expects each domain to be represented by a unique device pointer. SoC
+framework registers a set of initial OPPs per device with the OPP layer. This
+list is expected to be an optimally small number typically around 5 per device.
+This initial list contains a set of OPPs that the framework expects to be safely
+enabled by default in the system.
+
+Note on OPP Availability:
+------------------------
+As the system proceeds to operate, SoC framework may choose to make certain
+OPPs available or not available on each device based on various external
+factors. Example usage: Thermal management or other exceptional situations where
+SoC framework might choose to disable a higher frequency OPP to safely continue
+operations until that OPP could be re-enabled if possible.
+
+OPP library facilitates this concept in it's implementation. The following
+operational functions operate only on available opps:
+opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
+and opp_init_cpufreq_table
+
+opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for opp_enable/disable functions to make an opp available as required.
+
+WARNING: Users of OPP library should refresh their availability count using
+get_opp_count if opp_enable/disable functions are invoked for a device, the
+exact mechanism to trigger these or the notification mechanism to other
+dependent subsystems such as cpufreq are left to the discretion of the SoC
+specific framework which uses the OPP library. Similar care needs to be taken
+care to refresh the cpufreq table in cases of these operations.
+
+WARNING on OPP List locking mechanism:
+-------------------------------------------------
+OPP library uses RCU for exclusivity. RCU allows the query functions to operate
+in multiple contexts and this synchronization mechanism is optimal for a read
+intensive operations on data structure as the OPP library caters to.
+
+To ensure that the data retrieved are sane, the users such as SoC framework
+should ensure that the section of code operating on OPP queries are locked
+using RCU read locks. The opp_find_freq_{exact,ceil,floor},
+opp_get_{voltage, freq, opp_count} fall into this category.
+
+opp_{add,enable,disable} are updaters which use mutex and implement it's own
+RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+mutex to implment RCU updater strategy. These functions should *NOT* be called
+under RCU locks and other contexts that prevent blocking functions in RCU or
+mutex operations from working.
+
+2. Initial OPP List Registration
+================================
+The SoC implementation calls opp_add function iteratively to add OPPs per
+device. It is expected that the SoC framework will register the OPP entries
+optimally- typical numbers range to be less than 5. The list generated by
+registering the OPPs is maintained by OPP library throughout the device
+operation. The SoC framework can subsequently control the availability of the
+OPPs dynamically using the opp_enable / disable functions.
+
+opp_add - Add a new OPP for a specific domain represented by the device pointer.
+ The OPP is defined using the frequency and voltage. Once added, the OPP
+ is assumed to be available and control of it's availability can be done
+ with the opp_enable/disable functions. OPP library internally stores
+ and manages this information in the opp struct. This function may be
+ used by SoC framework to define a optimal list as per the demands of
+ SoC usage environment.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_add(mpu_dev, 1000000, 900000);
+ if (!r) {
+ pr_err("%s: unable to register mpu opp(%d)\n", r);
+ goto no_cpufreq;
+ }
+ /* Do cpufreq things */
+ no_cpufreq:
+ /* Do remaining things */
+ }
+
+3. OPP Search Functions
+=======================
+High level framework such as cpufreq operates on frequencies. To map the
+frequency back to the corresponding OPP, OPP library provides handy functions
+to search the OPP list that OPP library internally manages. These search
+functions return the matching pointer representing the opp if a match is
+found, else returns error. These errors are expected to be handled by standard
+error checks such as IS_ERR() and appropriate actions taken by the caller.
+
+opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+ availability. This function is especially useful to enable an OPP which
+ is not available by default.
+ Example: In a case when SoC framework detects a situation where a
+ higher frequency could be made available, it can use this function to
+ find the OPP prior to call the opp_enable to actually make it available.
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* dont operate on the pointer.. just do a sanity check.. */
+ if (IS_ERR(opp)) {
+ pr_err("frequency not disabled!\n");
+ /* trigger appropriate actions.. */
+ } else {
+ opp_enable(dev,1000000000);
+ }
+
+ NOTE: This is the only search function that operates on OPPs which are
+ not available.
+
+opp_find_freq_floor - Search for an available OPP which is *at most* the
+ provided frequency. This function is useful while searching for a lesser
+ match OR operating on OPP information in the order of decreasing
+ frequency.
+ Example: To find the highest opp for a device:
+ freq = ULONG_MAX;
+ rcu_read_lock();
+ opp_find_freq_floor(dev, &freq);
+ rcu_read_unlock();
+
+opp_find_freq_ceil - Search for an available OPP which is *at least* the
+ provided frequency. This function is useful while searching for a
+ higher match OR operating on OPP information in the order of increasing
+ frequency.
+ Example 1: To find the lowest opp for a device:
+ freq = 0;
+ rcu_read_lock();
+ opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ Example 2: A simplified implementation of a SoC cpufreq_driver->target:
+ soc_cpufreq_target(..)
+ {
+ /* Do stuff like policy checks etc. */
+ /* Find the best frequency match for the req */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ if (!IS_ERR(opp))
+ soc_switch_to_freq_voltage(freq);
+ else
+ /* do something when we cant satisfy the req */
+ /* do other stuff */
+ }
+
+4. OPP Availability Control Functions
+=====================================
+A default OPP list registered with the OPP library may not cater to all possible
+situation. The OPP library provides a set of functions to modify the
+availability of a OPP within the OPP list. This allows SoC frameworks to have
+fine grained dynamic control of which sets of OPPs are operationally available.
+These functions are intended to *temporarily* remove an OPP in conditions such
+as thermal considerations (e.g. don't use OPPx until the temperature drops).
+
+WARNING: Do not use these functions in interrupt context.
+
+opp_enable - Make a OPP available for operation.
+ Example: Lets say that 1GHz OPP is to be made available only if the
+ SoC temperature is lower than a certain threshold. The SoC framework
+ implementation might choose to do something as follows:
+ if (cur_temp < temp_low_thresh) {
+ /* Enable 1GHz if it was disabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_enable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+opp_disable - Make an OPP to be not available for operation
+ Example: Lets say that 1GHz OPP is to be disabled if the temperature
+ exceeds a threshold value. The SoC framework implementation might
+ choose to do something as follows:
+ if (cur_temp > temp_high_thresh) {
+ /* Disable 1GHz if it was enabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, true);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_disable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+5. OPP Data Retrieval Functions
+===============================
+Since OPP library abstracts away the OPP information, a set of functions to pull
+information from the OPP structure is necessary. Once an OPP pointer is
+retrieved using the search functions, the following functions can be used by SoC
+framework to retrieve the information represented inside the OPP layer.
+
+opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+ Example: At a cpufreq transition to a different frequency, SoC
+ framework requires to set the voltage represented by the OPP using
+ the regulator framework to the Power Management chip providing the
+ voltage.
+ soc_switch_to_freq_voltage(freq)
+ {
+ /* do things */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ v = opp_get_voltage(opp);
+ rcu_read_unlock();
+ if (v)
+ regulator_set_voltage(.., v);
+ /* do other things */
+ }
+
+opp_get_freq - Retrieve the freq represented by the opp pointer.
+ Example: Lets say the SoC framework uses a couple of helper functions
+ we could pass opp pointers instead of doing additional parameters to
+ handle quiet a bit of data parameters.
+ soc_cpufreq_target(..)
+ {
+ /* do things.. */
+ max_freq = ULONG_MAX;
+ rcu_read_lock();
+ max_opp = opp_find_freq_floor(dev,&max_freq);
+ requested_opp = opp_find_freq_ceil(dev,&freq);
+ if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
+ r = soc_test_validity(max_opp, requested_opp);
+ rcu_read_unlock();
+ /* do other things */
+ }
+ soc_test_validity(..)
+ {
+ if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+ return -EINVAL;
+ if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+ return -EINVAL;
+ /* do things.. */
+ }
+
+opp_get_opp_count - Retrieve the number of available opps for a device
+ Example: Lets say a co-processor in the SoC needs to know the available
+ frequencies in a table, the main processor can notify as following:
+ soc_notify_coproc_available_frequencies()
+ {
+ /* Do things */
+ rcu_read_lock();
+ num_available = opp_get_opp_count(dev);
+ speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
+ /* populate the table in increasing order */
+ freq = 0;
+ while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+ speeds[i] = freq;
+ freq++;
+ i++;
+ }
+ rcu_read_unlock();
+
+ soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
+ /* Do other things */
+ }
+
+6. Cpufreq Table Generation
+===========================
+opp_init_cpufreq_table - cpufreq framework typically is initialized with
+ cpufreq_frequency_table_cpuinfo which is provided with the list of
+ frequencies that are available for operation. This function provides
+ a ready to use conversion routine to translate the OPP layer's internal
+ information about the available frequencies into a format readily
+ providable to cpufreq.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_init_cpufreq_table(dev, &freq_table);
+ if (!r)
+ cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ /* Do other things */
+ }
+
+ NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
+ addition to CONFIG_PM as power management feature is required to
+ dynamically scale voltage and frequency in a system.
+
+7. Data Structures
+==================
+Typically an SoC contains multiple voltage domains which are variable. Each
+domain is represented by a device pointer. The relationship to OPP can be
+represented as follows:
+SoC
+ |- device 1
+ | |- opp 1 (availability, freq, voltage)
+ | |- opp 2 ..
+ ... ...
+ | `- opp n ..
+ |- device 2
+ ...
+ `- device m
+
+OPP library maintains a internal list that the SoC framework populates and
+accessed by various functions as described above. However, the structures
+representing the actual OPPs and domains are internal to the OPP library itself
+to allow for suitable abstraction reusable across systems.
+
+struct opp - The internal data structure of OPP library which is used to
+ represent an OPP. In addition to the freq, voltage, availability
+ information, it also contains internal book keeping information required
+ for the OPP library to operate on. Pointer to this structure is
+ provided back to the users such as SoC framework to be used as a
+ identifier for OPP in the interactions with OPP layer.
+
+ WARNING: The struct opp pointer should not be parsed or modified by the
+ users. The defaults of for an instance is populated by opp_add, but the
+ availability of the OPP can be modified by opp_enable/disable functions.
+
+struct device - This is used to identify a domain to the OPP layer. The
+ nature of the device and it's implementation is left to the user of
+ OPP library such as the SoC framework.
+
+Overall, in a simplistic view, the data structure operations is represented as
+following:
+
+Initialization / modification:
+ +-----+ /- opp_enable
+opp_add --> | opp | <-------
+ | +-----+ \- opp_disable
+ \-------> domain_info(device)
+
+Search functions:
+ /-- opp_find_freq_ceil ---\ +-----+
+domain_info<---- opp_find_freq_exact -----> | opp |
+ \-- opp_find_freq_floor ---/ +-----+
+
+Retrieval functions:
++-----+ /- opp_get_voltage
+| opp | <---
++-----+ \- opp_get_freq
+
+domain_info <- opp_get_opp_count
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index cbccf9a..abe46ed 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_OPS) += generic_ops.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
+obj-$(CONFIG_PM_OPP) += opp.o
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
new file mode 100644
index 0000000..abc5be5
--- /dev/null
+++ b/drivers/base/power/opp.c
@@ -0,0 +1,626 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/opp.h>
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ * |- device 1 (represents voltage domain 1)
+ * | |- opp 1 (availability, freq, voltage)
+ * | |- opp 2 ..
+ * ... ...
+ * | `- opp n ..
+ * |- device 2 (represents the next voltage domain)
+ * ...
+ * `- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct opp - Generic OPP description structure
+ * @node: opp list node. The nodes are maintained throughout the lifetime
+ * of boot. It is expected only an optimal set of OPPs are
+ * added to the library by the SoC framework.
+ * RCU usage: opp list is traversed with RCU locks. node
+ * modification is possible realtime, hence the modifications
+ * are protected by the dev_opp_list_lock for integrity.
+ * IMPORTANT: the opp nodes should be maintained in increasing
+ * order.
+ * @available: true/false - marks if this OPP as available or not
+ * @rate: Frequency in hertz
+ * @u_volt: Nominal voltage in microvolts corresponding to this OPP
+ * @dev_opp: points back to the device_opp struct this opp belongs to
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct opp {
+ struct list_head node;
+
+ bool available;
+ unsigned long rate;
+ unsigned long u_volt;
+
+ struct device_opp *dev_opp;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node: list node - contains the devices with OPPs that
+ * have been registered. Nodes once added are not modified in this
+ * list.
+ * RCU usage: nodes are not modified in the list of device_opp,
+ * however addition is possible and is secured by dev_opp_list_lock
+ * @dev: device pointer
+ * @opp_list: list of opps
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library
+ */
+struct device_opp {
+ struct list_head node;
+
+ struct device *dev;
+ struct list_head opp_list;
+};
+
+/*
+ * The root of the list of all devices. All device_opp structures branch off
+ * from here, with each device_opp containing the list of opp it supports in
+ * various states of availability.
+ */
+static LIST_HEAD(dev_opp_list);
+/* Lock to allow exclusive modification to the device and opp lists */
+static DEFINE_MUTEX(dev_opp_list_lock);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev: device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device. Does a RCU
+ * reader operation to grab the pointer needed.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * -EINVAL based on type of error.
+ *
+ * Locking: This function must be called under rcu_read_lock(). device_opp
+ * is a RCU protected pointer. This means that device_opp is valid as long
+ * as we are under RCU lock.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+ if (unlikely(IS_ERR_OR_NULL(dev))) {
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
+ if (tmp_dev_opp->dev == dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+
+ return dev_opp;
+}
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * @opp: opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_voltage(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long v = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ else
+ v = tmp_opp->u_volt;
+
+ return v;
+}
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * @opp: opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_freq(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long f = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ else
+ f = tmp_opp->rate;
+
+ return f;
+}
+
+/**
+ * opp_get_opp_count() - Get number of opps available in the opp list
+ * @dev: device for which we do this operation
+ *
+ * This function returns the number of available opps if there are any,
+ * else returns 0 if none or the corresponding error value.
+ *
+ * Locking: This function must be called under rcu_read_lock(). This function
+ * internally references two RCU protected structures: device_opp and opp which
+ * are safe as long as we are under a common RCU locked section.
+ */
+int opp_get_opp_count(struct device *dev)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp;
+ int count = 0;
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ dev_warn(dev, "%s: device not found in list\n", __func__);
+ return PTR_ERR(dev_opp);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available)
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * opp_find_freq_exact() - search for an exact frequency
+ * @dev: device for which we do this operation
+ * @freq: frequency to search for
+ * @is_available: true/false - match for available opp
+ *
+ * Searches for exact match in the opp list and returns pointer to the matching
+ * opp if found, else returns ERR_PTR in case of error and should be handled
+ * using IS_ERR.
+ *
+ * Note: available is a modifier for the search. if available=true, then the
+ * match is for exact matching frequency and is available in the stored OPP
+ * table. if false, the match is for exact frequency which is not available.
+ *
+ * This provides a mechanism to enable an opp which is not available currently
+ * or the opposite as well.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ int r = PTR_ERR(dev_opp);
+ dev_err(dev, "%s: device not found in list(%d)\n", __func__, r);
+ return ERR_PTR(r);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available == available &&
+ temp_opp->rate == freq) {
+ opp = temp_opp;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching ceil *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid param. freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available && temp_opp->rate >= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_floor() - Search for a rounded floor freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching floor *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid param. freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available) {
+ /* go to the next node, before choosing prev */
+ if (temp_opp->rate > *freq)
+ break;
+ else
+ opp = temp_opp;
+ }
+ }
+ if (!IS_ERR(opp))
+ *freq = opp->rate;
+
+ return opp;
+}
+
+/**
+ * opp_add() - Add an OPP table from a table definitions
+ * @dev: device for which we do this operation
+ * @freq: Frequency in Hz for this OPP
+ * @u_volt: Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+ struct device_opp *dev_opp = NULL;
+ struct opp *opp, *new_opp;
+ struct list_head *head;
+
+ /* allocate new OPP node */
+ new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to allocate new opp node\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Check for existing list for 'dev' */
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ /*
+ * Allocate a new device OPP table. In the infrequent case
+ * where a new device is needed to be added, we pay this
+ * penalty.
+ */
+ dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+ if (!dev_opp) {
+ mutex_unlock(&dev_opp_list_lock);
+ kfree(new_opp);
+ dev_warn(dev, "%s: Unable to alloc device structure\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ dev_opp->dev = dev;
+ INIT_LIST_HEAD(&dev_opp->opp_list);
+
+ /* Secure the device list modification */
+ list_add_rcu(&dev_opp->node, &dev_opp_list);
+ }
+
+ /* populate the opp table */
+ new_opp->dev_opp = dev_opp;
+ new_opp->rate = freq;
+ new_opp->u_volt = u_volt;
+ new_opp->available = true;
+
+ /* Insert new OPP in order of increasing frequency */
+ head = &dev_opp->opp_list;
+ list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+ if (new_opp->rate < opp->rate)
+ break;
+ else
+ head = &opp->node;
+ }
+
+ list_add_rcu(&new_opp->node, head);
+ mutex_unlock(&dev_opp_list_lock);
+
+ return 0;
+}
+
+/**
+ * opp_set_availability() - helper to set the availability of an opp
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to modify availability
+ * @availability_req: availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int opp_set_availability(struct device *dev, unsigned long freq,
+ bool availability_req)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+ struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+ int r = 0;
+
+ /* keep the node allocated */
+ new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to allocate opp\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Find the device_opp */
+ list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+ if (dev == tmp_dev_opp->dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+ if (IS_ERR(dev_opp)) {
+ r = PTR_ERR(dev_opp);
+ dev_warn(dev, "%s: Unable to find device in list\n", __func__);
+ goto unlock;
+ }
+
+ /* Do we have the frequency? */
+ list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+ if (tmp_opp->rate == freq) {
+ opp = tmp_opp;
+ break;
+ }
+ }
+ if (IS_ERR(opp)) {
+ r = PTR_ERR(opp);
+ goto unlock;
+ }
+
+ /* Is update really needed? */
+ if (opp->available == availability_req)
+ goto unlock;
+ /* copy the old data over */
+ *new_opp = *opp;
+
+ /* plug in new node */
+ new_opp->available = availability_req;
+
+ list_replace_rcu(&opp->node, &new_opp->node);
+ mutex_unlock(&dev_opp_list_lock);
+ synchronize_rcu();
+
+ /* clean up old opp */
+ new_opp = opp;
+ goto out;
+
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+out:
+ kfree(new_opp);
+ return r;
+}
+
+/**
+ * opp_enable() - Enable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to enable
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value. It is meant to be used for users an OPP available
+ * after being temporarily made unavailable with opp_disable.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_enable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, true);
+}
+
+/**
+ * opp_disable() - Disable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to disable
+ *
+ * Disables a provided opp. If the operation is valid, this returns
+ * 0, else the corresponding error value. It is meant to be a temporary
+ * control by users to make this OPP not available until the circumstances are
+ * right to make it available again (with a call to opp_enable).
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_disable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, false);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/**
+ * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev: device for which we do this operation
+ * @table: Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * To simplify the logic, we pretend we are updater and hold relevant mutex here
+ * Callers should ensure that this function is *NOT* called under RCU protection
+ * or in contexts where mutex locking cannot be used.
+ */
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ struct device_opp *dev_opp;
+ struct opp *opp;
+ struct cpufreq_frequency_table *freq_table;
+ int i = 0;
+
+ /* Pretend as if I am an updater */
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Unable to find device in list\n", __func__);
+ return PTR_ERR(dev_opp);
+ }
+
+ freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+ (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+ if (!freq_table) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Failed to allocate frequency table\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ list_for_each_entry(opp, &dev_opp->opp_list, node) {
+ if (opp->available) {
+ freq_table[i].index = i;
+ freq_table[i].frequency = opp->rate / 1000;
+ i++;
+ }
+ }
+ mutex_unlock(&dev_opp_list_lock);
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *table = &freq_table[0];
+
+ return 0;
+}
+#endif /* CONFIG_CPU_FREQ */
diff --git a/include/linux/opp.h b/include/linux/opp.h
new file mode 100644
index 0000000..5449945
--- /dev/null
+++ b/include/linux/opp.h
@@ -0,0 +1,105 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+
+struct opp;
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long opp_get_voltage(struct opp *opp);
+
+unsigned long opp_get_freq(struct opp *opp);
+
+int opp_get_opp_count(struct device *dev);
+
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available);
+
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
+
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
+
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
+
+int opp_enable(struct device *dev, unsigned long freq);
+
+int opp_disable(struct device *dev, unsigned long freq);
+
+#else
+static inline unsigned long opp_get_voltage(struct opp *opp)
+{
+ return 0;
+}
+
+static inline unsigned long opp_get_freq(struct opp *opp)
+{
+ return 0;
+}
+
+static inline int opp_get_opp_count(struct device *dev)
+{
+ return 0;
+}
+
+static inline struct opp *opp_find_freq_exact(struct device *dev,
+ unsigned long freq, bool available)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_floor(struct device *dev,
+ unsigned long *freq)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_ceil(struct device *dev,
+ unsigned long *freq)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline int opp_add(struct device *dev, unsigned long freq,
+ unsigned long u_volt)
+{
+ return -EINVAL;
+}
+
+static inline int opp_enable(struct device *dev, unsigned long freq)
+{
+ return 0;
+}
+
+static inline int opp_disable(struct device *dev, unsigned long freq)
+{
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table);
+#else
+static inline int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_CPU_FREQ */
+
+#endif /* __LINUX_OPP_H__ */
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ca6066a..634eab6 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -242,3 +242,17 @@ config PM_OPS
bool
depends on PM_SLEEP || PM_RUNTIME
default y
+
+config PM_OPP
+ bool "Enable Operating Performance Point(OPP) Layer library"
+ depends on PM
+ ---help---
+ SOCs have a standard set of tuples consisting of frequency and
+ voltage pairs that the device will support per voltage domain. This
+ is called Operating Performance Point or OPP. The actual definitions
+ of OPP varies over silicon within the same family of devices.
+
+ OPP layer organizes the data internally using device pointers
+ representing individual voltage domains and provides SOC
+ implementations a ready to use framework to manage OPPs.
+ For more information, read <file:Documentation/power/opp.txt>
--
1.6.3.3
^ permalink raw reply related
* [PATCH v7] power: introduce library for device-specific OPPs
From: Nishanth Menon @ 2010-10-08 3:02 UTC (permalink / raw)
To: linux-pm, lkml; +Cc: Paul, l-o, l-a
In-Reply-To: <[PATCH] power: introduce library for device-specific OPPs>
SoCs have a standard set of tuples consisting of frequency and
voltage pairs that the device will support per voltage domain. These
are called Operating Performance Points or OPPs. The actual
definitions of OPP varies over silicon versions. For a specific domain,
we can have a set of {frequency, voltage} pairs. As the kernel boots
and more information is available, a default set of these are activated
based on the precise nature of device. Further on operation, based on
conditions prevailing in the system (such as temperature), some OPP
availability may be temporarily controlled by the SoC frameworks.
To implement an OPP, some sort of power management support is necessary
hence this library depends on CONFIG_PM.
Contributions include:
Sanjeev Premi for the initial concept:
http://patchwork.kernel.org/patch/50998/
Kevin Hilman for converting original design to device-based
Kevin Hilman and Paul Walmsey for cleaning up many of the function
abstractions, improvements and data structure handling
Romit Dasgupta for using enums instead of opp pointers
Thara Gopinath, Eduardo Valentin and Vishwanath BS for fixes and
cleanups.
Linus Walleij for recommending this layer be made generic for usage
in other architectures beyond OMAP and ARM.
Mark Brown, Andrew Morton, Rafael J Wysocki, Paul E McKenney for valuable
improvements.
Discussions and comments from:
http://marc.info/?l=linux-omap&m=126033945313269&w=2
http://marc.info/?l=linux-omap&m=125482970102327&w=2
http://marc.info/?t=125809247500002&r=1&w=2
http://marc.info/?l=linux-omap&m=126025973426007&w=2
http://marc.info/?t=128152609200064&r=1&w=2
http://marc.info/?t=128468723000002&r=1&w=2
incorporated.
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Phil Carmody <ext-phil.2.carmody@nokia.com>
Cc: Roberto Granados Dorado <x0095451@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Tero Kristo <Tero.Kristo@nokia.com>
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath BS <vishwanath.bs@ti.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
V7:
removed pr_fmt and used dev_err/warn instead of pr_xx family where
possible
replaced out1 label with unlock to make it readable
Accepted a offline suggestion to use IS_ERR_OR_NULL to replace
!var || IS_ERR(var) check in find_device_opp, opp_get_voltage &
opp_get_freq
V6: https://patchwork.kernel.org/patch/235591/
mutexes reduced to a single one. dev_opp_list_lock now protects
both the devices and the opp lists, doc updated accordingly.
fixed opp_add removed an irrelevant find_device_opp, used IS_ERR to
check pointer
fixed updater routines to remove unnecessary reader operations.
comments from v5 not included in v6:
- synchronize_rcu() is not needed after list_add_rcu as pointed by
Paul in http://marc.info/?l=linux-omap&m=128535708720191&w=2
I have retained it's usage after list_replace_rcu as with v4.
- Temporary release of mutex in opp_add under if (IS_ERR(dev_opp)) {
Rationale:
If two parallel calls to opp_add on the same device node which
is not yet added in the list can cause data structure integrity
issues. For example:
c1: holds mutex dev_opp_list_lock
c2: starts and is blocked on dev_opp_list_lock mutex here
dev_opp = find_device_opp(dev); [c1 in progress here]
if (IS_ERR(dev_opp)) {
If c1 releases dev_opp_list_lock here, c2 can proceed
to call find_device_opp which will return error and will
cause following allocation to take place for same device
node.
dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
This is undesirable as it will result in an additional node added
for the same device (since the device is the same, c1 should have
added the new node and c2 should have just added an opp).
Since the actual addition of a device node by itself is rare,
kzalloc is a tiny penalty to pay for integrity of the data structure.
The other option being to move the kzalloc before the mutex locking,
but, that will cause dev_opp allocation overhead for every opp
addition.
All other comments have been incorporated.
Tested with cpufreq on SDP3630 (TI OMAP3630) with lockdep debugging to
catch races.
V5: https://patchwork.kernel.org/patch/223272/
opp pointers were being passed to callers outside rcu locks, this
causes the pointers to be potentially invalid between calls if
opp_enable/disable calls take place.
The solution for this cannot be reference counters either, as
opp pointer without control of opp library and rcu locks are
completely untrustworthy. The better approach is to enforce
restrictions on callers of query and retrieval functions to wrap
the relevant parts under rcu locks. This allows for tremendous
flexibility in the way opp libraries can be used as the users
can optimize their implementation based on the requirements.
NOTE: find_device_opp is implicitly wrapped as a result.
(ref, v4 comments)
One more side-effect has been that the opp_enable and disable
functions changed their prototypes to make it a little more easier
for the users to use them without having to get the pointers before
hand, as well as do the functionality that is being provided currently
as well.
opp_init_cpufreq_table now returns int and result of operation for
callers to adequately handle their error conditions.
pr_fmt is being used instead of duplicating "%s" .. __func__ with
every pr_xxx call.
Documentation update to reflect these.
Sample usage:
http://pastebin.mozilla.org/802375: cleanups for omap pm layer
http://pastebin.mozilla.org/802374: omap opp initialization
V4: http://marc.info/?t=128533285000002&r=1&w=2
Cc list trimmed to just the MLs.
RCU implementation - thanks for the pointers Rafael
re-tested on OMAP3630 with lock debugging enabled including cpufreq,
idle paths and "exception cases - enable/disable".
available_opp_count removed as it complicated the updates altogether
+ the usage latencies are not too high given small lists.
In removed list_reverse usage as rcu has no list reverse equivalents
+ searching either direction has no real difference when the list
is ordered.
change in protos for get_{voltage,frequency} - const removed from
parameter as rcu_dereference causes build warnings
introduced opp_set_availability helper to wrap common code between
opp_{enable,disable} - leaving these as is as they are more readable
from usage perspective + these are not meant to be used in hot paths
anyways.
Header guard __ASM_OPP_H replaced with __LINUX_OPP_H__ for opp.h
V3: https://patchwork.kernel.org/patch/200382/
Bunch of documentation update based on feedback
removed opp_def - opp_add enables the opp by default
lock usage optimization
Sample usage:
http://pastebin.mozilla.org/794786 -> cleanups for OMAP power
http://pastebin.mozilla.org/794787 -> Sample OPP initialization for OMAP
V2: https://patchwork.kernel.org/patch/189532/
Incorporated review comments from v1. major changes being:
$subject change to reflect this is for power.
Documentation revamp and including it in the patch :)
OPP_DEF removed - lets introduce this if needed or leave it to
SOC frameworks to organize code as needed.
Rename of enable to available to better reflect the intent
few fixes and typos
Introduced mutex based locking for controlling access to list
modification (note: query functions are still unsafe- rationale
in the patch below)
A new home for opp.c in drivers/base/power (moved from lib/)
A few optimization in function flow and additional error checks
added to exposed functions
offline aligned with Kevin for cleaning up the copyrights
V1: http://marc.info/?t=128468723000002&r=1&w=2
Documentation/power/00-INDEX | 2 +
Documentation/power/opp.txt | 373 +++++++++++++++++++++++++
drivers/base/power/Makefile | 1 +
drivers/base/power/opp.c | 626 ++++++++++++++++++++++++++++++++++++++++++
include/linux/opp.h | 105 +++++++
kernel/power/Kconfig | 14 +
6 files changed, 1121 insertions(+), 0 deletions(-)
create mode 100644 Documentation/power/opp.txt
create mode 100644 drivers/base/power/opp.c
create mode 100644 include/linux/opp.h
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index fb742c2..45e9d4a 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -14,6 +14,8 @@ interface.txt
- Power management user interface in /sys/power
notifiers.txt
- Registering suspend notifiers in device drivers
+opp.txt
+ - Operating Performance Point library
pci.txt
- How the PCI Subsystem Does Power Management
pm_qos_interface.txt
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
new file mode 100644
index 0000000..b309e30
--- /dev/null
+++ b/Documentation/power/opp.txt
@@ -0,0 +1,373 @@
+*=============*
+* OPP Library *
+*=============*
+
+Contents
+--------
+1. Introduction
+2. Initial OPP List Registration
+3. OPP Search Functions
+4. OPP Availability Control Functions
+5. OPP Data Retrieval Functions
+6. Cpufreq Table Generation
+7. Data Structures
+
+1. Introduction
+===============
+Complex SoCs of today consists of a multiple sub-modules working in conjunction.
+In an operational system executing varied use cases, not all modules in the SoC
+need to function at their highest performing frequency all the time. To
+facilitate this, sub-modules in a SoC are grouped into domains, allowing some
+domains to run at lower voltage and frequency while other domains are loaded
+more. The set of discrete tuples consisting of frequency and voltage pairs that
+the device will support per domain are called Operating Performance Points or
+OPPs.
+
+OPP library provides a set of helper functions to organize and query the OPP
+information. The library is located in drivers/base/power/opp.c and the header
+is located in include/linux/opp.h. OPP library can be enabled by enabling
+CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
+CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+optionally boot at a certain OPP without needing cpufreq.
+
+Typical usage of the OPP library is as follows:
+(users) -> registers a set of default OPPs -> (library)
+SoC framework -> modifies on required cases certain OPPs -> OPP layer
+ -> queries to search/retrieve information ->
+
+OPP layer expects each domain to be represented by a unique device pointer. SoC
+framework registers a set of initial OPPs per device with the OPP layer. This
+list is expected to be an optimally small number typically around 5 per device.
+This initial list contains a set of OPPs that the framework expects to be safely
+enabled by default in the system.
+
+Note on OPP Availability:
+------------------------
+As the system proceeds to operate, SoC framework may choose to make certain
+OPPs available or not available on each device based on various external
+factors. Example usage: Thermal management or other exceptional situations where
+SoC framework might choose to disable a higher frequency OPP to safely continue
+operations until that OPP could be re-enabled if possible.
+
+OPP library facilitates this concept in it's implementation. The following
+operational functions operate only on available opps:
+opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
+and opp_init_cpufreq_table
+
+opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for opp_enable/disable functions to make an opp available as required.
+
+WARNING: Users of OPP library should refresh their availability count using
+get_opp_count if opp_enable/disable functions are invoked for a device, the
+exact mechanism to trigger these or the notification mechanism to other
+dependent subsystems such as cpufreq are left to the discretion of the SoC
+specific framework which uses the OPP library. Similar care needs to be taken
+care to refresh the cpufreq table in cases of these operations.
+
+WARNING on OPP List locking mechanism:
+-------------------------------------------------
+OPP library uses RCU for exclusivity. RCU allows the query functions to operate
+in multiple contexts and this synchronization mechanism is optimal for a read
+intensive operations on data structure as the OPP library caters to.
+
+To ensure that the data retrieved are sane, the users such as SoC framework
+should ensure that the section of code operating on OPP queries are locked
+using RCU read locks. The opp_find_freq_{exact,ceil,floor},
+opp_get_{voltage, freq, opp_count} fall into this category.
+
+opp_{add,enable,disable} are updaters which use mutex and implement it's own
+RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+mutex to implment RCU updater strategy. These functions should *NOT* be called
+under RCU locks and other contexts that prevent blocking functions in RCU or
+mutex operations from working.
+
+2. Initial OPP List Registration
+================================
+The SoC implementation calls opp_add function iteratively to add OPPs per
+device. It is expected that the SoC framework will register the OPP entries
+optimally- typical numbers range to be less than 5. The list generated by
+registering the OPPs is maintained by OPP library throughout the device
+operation. The SoC framework can subsequently control the availability of the
+OPPs dynamically using the opp_enable / disable functions.
+
+opp_add - Add a new OPP for a specific domain represented by the device pointer.
+ The OPP is defined using the frequency and voltage. Once added, the OPP
+ is assumed to be available and control of it's availability can be done
+ with the opp_enable/disable functions. OPP library internally stores
+ and manages this information in the opp struct. This function may be
+ used by SoC framework to define a optimal list as per the demands of
+ SoC usage environment.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_add(mpu_dev, 1000000, 900000);
+ if (!r) {
+ pr_err("%s: unable to register mpu opp(%d)\n", r);
+ goto no_cpufreq;
+ }
+ /* Do cpufreq things */
+ no_cpufreq:
+ /* Do remaining things */
+ }
+
+3. OPP Search Functions
+=======================
+High level framework such as cpufreq operates on frequencies. To map the
+frequency back to the corresponding OPP, OPP library provides handy functions
+to search the OPP list that OPP library internally manages. These search
+functions return the matching pointer representing the opp if a match is
+found, else returns error. These errors are expected to be handled by standard
+error checks such as IS_ERR() and appropriate actions taken by the caller.
+
+opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+ availability. This function is especially useful to enable an OPP which
+ is not available by default.
+ Example: In a case when SoC framework detects a situation where a
+ higher frequency could be made available, it can use this function to
+ find the OPP prior to call the opp_enable to actually make it available.
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* dont operate on the pointer.. just do a sanity check.. */
+ if (IS_ERR(opp)) {
+ pr_err("frequency not disabled!\n");
+ /* trigger appropriate actions.. */
+ } else {
+ opp_enable(dev,1000000000);
+ }
+
+ NOTE: This is the only search function that operates on OPPs which are
+ not available.
+
+opp_find_freq_floor - Search for an available OPP which is *at most* the
+ provided frequency. This function is useful while searching for a lesser
+ match OR operating on OPP information in the order of decreasing
+ frequency.
+ Example: To find the highest opp for a device:
+ freq = ULONG_MAX;
+ rcu_read_lock();
+ opp_find_freq_floor(dev, &freq);
+ rcu_read_unlock();
+
+opp_find_freq_ceil - Search for an available OPP which is *at least* the
+ provided frequency. This function is useful while searching for a
+ higher match OR operating on OPP information in the order of increasing
+ frequency.
+ Example 1: To find the lowest opp for a device:
+ freq = 0;
+ rcu_read_lock();
+ opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ Example 2: A simplified implementation of a SoC cpufreq_driver->target:
+ soc_cpufreq_target(..)
+ {
+ /* Do stuff like policy checks etc. */
+ /* Find the best frequency match for the req */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ if (!IS_ERR(opp))
+ soc_switch_to_freq_voltage(freq);
+ else
+ /* do something when we cant satisfy the req */
+ /* do other stuff */
+ }
+
+4. OPP Availability Control Functions
+=====================================
+A default OPP list registered with the OPP library may not cater to all possible
+situation. The OPP library provides a set of functions to modify the
+availability of a OPP within the OPP list. This allows SoC frameworks to have
+fine grained dynamic control of which sets of OPPs are operationally available.
+These functions are intended to *temporarily* remove an OPP in conditions such
+as thermal considerations (e.g. don't use OPPx until the temperature drops).
+
+WARNING: Do not use these functions in interrupt context.
+
+opp_enable - Make a OPP available for operation.
+ Example: Lets say that 1GHz OPP is to be made available only if the
+ SoC temperature is lower than a certain threshold. The SoC framework
+ implementation might choose to do something as follows:
+ if (cur_temp < temp_low_thresh) {
+ /* Enable 1GHz if it was disabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_enable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+opp_disable - Make an OPP to be not available for operation
+ Example: Lets say that 1GHz OPP is to be disabled if the temperature
+ exceeds a threshold value. The SoC framework implementation might
+ choose to do something as follows:
+ if (cur_temp > temp_high_thresh) {
+ /* Disable 1GHz if it was enabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, true);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_disable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+5. OPP Data Retrieval Functions
+===============================
+Since OPP library abstracts away the OPP information, a set of functions to pull
+information from the OPP structure is necessary. Once an OPP pointer is
+retrieved using the search functions, the following functions can be used by SoC
+framework to retrieve the information represented inside the OPP layer.
+
+opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+ Example: At a cpufreq transition to a different frequency, SoC
+ framework requires to set the voltage represented by the OPP using
+ the regulator framework to the Power Management chip providing the
+ voltage.
+ soc_switch_to_freq_voltage(freq)
+ {
+ /* do things */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ v = opp_get_voltage(opp);
+ rcu_read_unlock();
+ if (v)
+ regulator_set_voltage(.., v);
+ /* do other things */
+ }
+
+opp_get_freq - Retrieve the freq represented by the opp pointer.
+ Example: Lets say the SoC framework uses a couple of helper functions
+ we could pass opp pointers instead of doing additional parameters to
+ handle quiet a bit of data parameters.
+ soc_cpufreq_target(..)
+ {
+ /* do things.. */
+ max_freq = ULONG_MAX;
+ rcu_read_lock();
+ max_opp = opp_find_freq_floor(dev,&max_freq);
+ requested_opp = opp_find_freq_ceil(dev,&freq);
+ if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
+ r = soc_test_validity(max_opp, requested_opp);
+ rcu_read_unlock();
+ /* do other things */
+ }
+ soc_test_validity(..)
+ {
+ if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+ return -EINVAL;
+ if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+ return -EINVAL;
+ /* do things.. */
+ }
+
+opp_get_opp_count - Retrieve the number of available opps for a device
+ Example: Lets say a co-processor in the SoC needs to know the available
+ frequencies in a table, the main processor can notify as following:
+ soc_notify_coproc_available_frequencies()
+ {
+ /* Do things */
+ rcu_read_lock();
+ num_available = opp_get_opp_count(dev);
+ speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
+ /* populate the table in increasing order */
+ freq = 0;
+ while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+ speeds[i] = freq;
+ freq++;
+ i++;
+ }
+ rcu_read_unlock();
+
+ soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
+ /* Do other things */
+ }
+
+6. Cpufreq Table Generation
+===========================
+opp_init_cpufreq_table - cpufreq framework typically is initialized with
+ cpufreq_frequency_table_cpuinfo which is provided with the list of
+ frequencies that are available for operation. This function provides
+ a ready to use conversion routine to translate the OPP layer's internal
+ information about the available frequencies into a format readily
+ providable to cpufreq.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_init_cpufreq_table(dev, &freq_table);
+ if (!r)
+ cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ /* Do other things */
+ }
+
+ NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
+ addition to CONFIG_PM as power management feature is required to
+ dynamically scale voltage and frequency in a system.
+
+7. Data Structures
+==================
+Typically an SoC contains multiple voltage domains which are variable. Each
+domain is represented by a device pointer. The relationship to OPP can be
+represented as follows:
+SoC
+ |- device 1
+ | |- opp 1 (availability, freq, voltage)
+ | |- opp 2 ..
+ ... ...
+ | `- opp n ..
+ |- device 2
+ ...
+ `- device m
+
+OPP library maintains a internal list that the SoC framework populates and
+accessed by various functions as described above. However, the structures
+representing the actual OPPs and domains are internal to the OPP library itself
+to allow for suitable abstraction reusable across systems.
+
+struct opp - The internal data structure of OPP library which is used to
+ represent an OPP. In addition to the freq, voltage, availability
+ information, it also contains internal book keeping information required
+ for the OPP library to operate on. Pointer to this structure is
+ provided back to the users such as SoC framework to be used as a
+ identifier for OPP in the interactions with OPP layer.
+
+ WARNING: The struct opp pointer should not be parsed or modified by the
+ users. The defaults of for an instance is populated by opp_add, but the
+ availability of the OPP can be modified by opp_enable/disable functions.
+
+struct device - This is used to identify a domain to the OPP layer. The
+ nature of the device and it's implementation is left to the user of
+ OPP library such as the SoC framework.
+
+Overall, in a simplistic view, the data structure operations is represented as
+following:
+
+Initialization / modification:
+ +-----+ /- opp_enable
+opp_add --> | opp | <-------
+ | +-----+ \- opp_disable
+ \-------> domain_info(device)
+
+Search functions:
+ /-- opp_find_freq_ceil ---\ +-----+
+domain_info<---- opp_find_freq_exact -----> | opp |
+ \-- opp_find_freq_floor ---/ +-----+
+
+Retrieval functions:
++-----+ /- opp_get_voltage
+| opp | <---
++-----+ \- opp_get_freq
+
+domain_info <- opp_get_opp_count
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index cbccf9a..abe46ed 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_OPS) += generic_ops.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
+obj-$(CONFIG_PM_OPP) += opp.o
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
new file mode 100644
index 0000000..abc5be5
--- /dev/null
+++ b/drivers/base/power/opp.c
@@ -0,0 +1,626 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/opp.h>
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ * |- device 1 (represents voltage domain 1)
+ * | |- opp 1 (availability, freq, voltage)
+ * | |- opp 2 ..
+ * ... ...
+ * | `- opp n ..
+ * |- device 2 (represents the next voltage domain)
+ * ...
+ * `- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct opp - Generic OPP description structure
+ * @node: opp list node. The nodes are maintained throughout the lifetime
+ * of boot. It is expected only an optimal set of OPPs are
+ * added to the library by the SoC framework.
+ * RCU usage: opp list is traversed with RCU locks. node
+ * modification is possible realtime, hence the modifications
+ * are protected by the dev_opp_list_lock for integrity.
+ * IMPORTANT: the opp nodes should be maintained in increasing
+ * order.
+ * @available: true/false - marks if this OPP as available or not
+ * @rate: Frequency in hertz
+ * @u_volt: Nominal voltage in microvolts corresponding to this OPP
+ * @dev_opp: points back to the device_opp struct this opp belongs to
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct opp {
+ struct list_head node;
+
+ bool available;
+ unsigned long rate;
+ unsigned long u_volt;
+
+ struct device_opp *dev_opp;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node: list node - contains the devices with OPPs that
+ * have been registered. Nodes once added are not modified in this
+ * list.
+ * RCU usage: nodes are not modified in the list of device_opp,
+ * however addition is possible and is secured by dev_opp_list_lock
+ * @dev: device pointer
+ * @opp_list: list of opps
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library
+ */
+struct device_opp {
+ struct list_head node;
+
+ struct device *dev;
+ struct list_head opp_list;
+};
+
+/*
+ * The root of the list of all devices. All device_opp structures branch off
+ * from here, with each device_opp containing the list of opp it supports in
+ * various states of availability.
+ */
+static LIST_HEAD(dev_opp_list);
+/* Lock to allow exclusive modification to the device and opp lists */
+static DEFINE_MUTEX(dev_opp_list_lock);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev: device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device. Does a RCU
+ * reader operation to grab the pointer needed.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * -EINVAL based on type of error.
+ *
+ * Locking: This function must be called under rcu_read_lock(). device_opp
+ * is a RCU protected pointer. This means that device_opp is valid as long
+ * as we are under RCU lock.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+ if (unlikely(IS_ERR_OR_NULL(dev))) {
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
+ if (tmp_dev_opp->dev == dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+
+ return dev_opp;
+}
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * @opp: opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_voltage(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long v = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ else
+ v = tmp_opp->u_volt;
+
+ return v;
+}
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * @opp: opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_freq(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long f = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ else
+ f = tmp_opp->rate;
+
+ return f;
+}
+
+/**
+ * opp_get_opp_count() - Get number of opps available in the opp list
+ * @dev: device for which we do this operation
+ *
+ * This function returns the number of available opps if there are any,
+ * else returns 0 if none or the corresponding error value.
+ *
+ * Locking: This function must be called under rcu_read_lock(). This function
+ * internally references two RCU protected structures: device_opp and opp which
+ * are safe as long as we are under a common RCU locked section.
+ */
+int opp_get_opp_count(struct device *dev)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp;
+ int count = 0;
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ dev_warn(dev, "%s: device not found in list\n", __func__);
+ return PTR_ERR(dev_opp);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available)
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * opp_find_freq_exact() - search for an exact frequency
+ * @dev: device for which we do this operation
+ * @freq: frequency to search for
+ * @is_available: true/false - match for available opp
+ *
+ * Searches for exact match in the opp list and returns pointer to the matching
+ * opp if found, else returns ERR_PTR in case of error and should be handled
+ * using IS_ERR.
+ *
+ * Note: available is a modifier for the search. if available=true, then the
+ * match is for exact matching frequency and is available in the stored OPP
+ * table. if false, the match is for exact frequency which is not available.
+ *
+ * This provides a mechanism to enable an opp which is not available currently
+ * or the opposite as well.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ int r = PTR_ERR(dev_opp);
+ dev_err(dev, "%s: device not found in list(%d)\n", __func__, r);
+ return ERR_PTR(r);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available == available &&
+ temp_opp->rate == freq) {
+ opp = temp_opp;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching ceil *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid param. freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available && temp_opp->rate >= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_floor() - Search for a rounded floor freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching floor *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid param. freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available) {
+ /* go to the next node, before choosing prev */
+ if (temp_opp->rate > *freq)
+ break;
+ else
+ opp = temp_opp;
+ }
+ }
+ if (!IS_ERR(opp))
+ *freq = opp->rate;
+
+ return opp;
+}
+
+/**
+ * opp_add() - Add an OPP table from a table definitions
+ * @dev: device for which we do this operation
+ * @freq: Frequency in Hz for this OPP
+ * @u_volt: Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+ struct device_opp *dev_opp = NULL;
+ struct opp *opp, *new_opp;
+ struct list_head *head;
+
+ /* allocate new OPP node */
+ new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to allocate new opp node\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Check for existing list for 'dev' */
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ /*
+ * Allocate a new device OPP table. In the infrequent case
+ * where a new device is needed to be added, we pay this
+ * penalty.
+ */
+ dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+ if (!dev_opp) {
+ mutex_unlock(&dev_opp_list_lock);
+ kfree(new_opp);
+ dev_warn(dev, "%s: Unable to alloc device structure\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ dev_opp->dev = dev;
+ INIT_LIST_HEAD(&dev_opp->opp_list);
+
+ /* Secure the device list modification */
+ list_add_rcu(&dev_opp->node, &dev_opp_list);
+ }
+
+ /* populate the opp table */
+ new_opp->dev_opp = dev_opp;
+ new_opp->rate = freq;
+ new_opp->u_volt = u_volt;
+ new_opp->available = true;
+
+ /* Insert new OPP in order of increasing frequency */
+ head = &dev_opp->opp_list;
+ list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+ if (new_opp->rate < opp->rate)
+ break;
+ else
+ head = &opp->node;
+ }
+
+ list_add_rcu(&new_opp->node, head);
+ mutex_unlock(&dev_opp_list_lock);
+
+ return 0;
+}
+
+/**
+ * opp_set_availability() - helper to set the availability of an opp
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to modify availability
+ * @availability_req: availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int opp_set_availability(struct device *dev, unsigned long freq,
+ bool availability_req)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+ struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+ int r = 0;
+
+ /* keep the node allocated */
+ new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to allocate opp\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Find the device_opp */
+ list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+ if (dev == tmp_dev_opp->dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+ if (IS_ERR(dev_opp)) {
+ r = PTR_ERR(dev_opp);
+ dev_warn(dev, "%s: Unable to find device in list\n", __func__);
+ goto unlock;
+ }
+
+ /* Do we have the frequency? */
+ list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+ if (tmp_opp->rate == freq) {
+ opp = tmp_opp;
+ break;
+ }
+ }
+ if (IS_ERR(opp)) {
+ r = PTR_ERR(opp);
+ goto unlock;
+ }
+
+ /* Is update really needed? */
+ if (opp->available == availability_req)
+ goto unlock;
+ /* copy the old data over */
+ *new_opp = *opp;
+
+ /* plug in new node */
+ new_opp->available = availability_req;
+
+ list_replace_rcu(&opp->node, &new_opp->node);
+ mutex_unlock(&dev_opp_list_lock);
+ synchronize_rcu();
+
+ /* clean up old opp */
+ new_opp = opp;
+ goto out;
+
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+out:
+ kfree(new_opp);
+ return r;
+}
+
+/**
+ * opp_enable() - Enable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to enable
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value. It is meant to be used for users an OPP available
+ * after being temporarily made unavailable with opp_disable.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_enable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, true);
+}
+
+/**
+ * opp_disable() - Disable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to disable
+ *
+ * Disables a provided opp. If the operation is valid, this returns
+ * 0, else the corresponding error value. It is meant to be a temporary
+ * control by users to make this OPP not available until the circumstances are
+ * right to make it available again (with a call to opp_enable).
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_disable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, false);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/**
+ * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev: device for which we do this operation
+ * @table: Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * To simplify the logic, we pretend we are updater and hold relevant mutex here
+ * Callers should ensure that this function is *NOT* called under RCU protection
+ * or in contexts where mutex locking cannot be used.
+ */
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ struct device_opp *dev_opp;
+ struct opp *opp;
+ struct cpufreq_frequency_table *freq_table;
+ int i = 0;
+
+ /* Pretend as if I am an updater */
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Unable to find device in list\n", __func__);
+ return PTR_ERR(dev_opp);
+ }
+
+ freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+ (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+ if (!freq_table) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Failed to allocate frequency table\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ list_for_each_entry(opp, &dev_opp->opp_list, node) {
+ if (opp->available) {
+ freq_table[i].index = i;
+ freq_table[i].frequency = opp->rate / 1000;
+ i++;
+ }
+ }
+ mutex_unlock(&dev_opp_list_lock);
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *table = &freq_table[0];
+
+ return 0;
+}
+#endif /* CONFIG_CPU_FREQ */
diff --git a/include/linux/opp.h b/include/linux/opp.h
new file mode 100644
index 0000000..5449945
--- /dev/null
+++ b/include/linux/opp.h
@@ -0,0 +1,105 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+
+struct opp;
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long opp_get_voltage(struct opp *opp);
+
+unsigned long opp_get_freq(struct opp *opp);
+
+int opp_get_opp_count(struct device *dev);
+
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available);
+
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
+
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
+
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
+
+int opp_enable(struct device *dev, unsigned long freq);
+
+int opp_disable(struct device *dev, unsigned long freq);
+
+#else
+static inline unsigned long opp_get_voltage(struct opp *opp)
+{
+ return 0;
+}
+
+static inline unsigned long opp_get_freq(struct opp *opp)
+{
+ return 0;
+}
+
+static inline int opp_get_opp_count(struct device *dev)
+{
+ return 0;
+}
+
+static inline struct opp *opp_find_freq_exact(struct device *dev,
+ unsigned long freq, bool available)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_floor(struct device *dev,
+ unsigned long *freq)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_ceil(struct device *dev,
+ unsigned long *freq)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline int opp_add(struct device *dev, unsigned long freq,
+ unsigned long u_volt)
+{
+ return -EINVAL;
+}
+
+static inline int opp_enable(struct device *dev, unsigned long freq)
+{
+ return 0;
+}
+
+static inline int opp_disable(struct device *dev, unsigned long freq)
+{
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table);
+#else
+static inline int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_CPU_FREQ */
+
+#endif /* __LINUX_OPP_H__ */
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ca6066a..634eab6 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -242,3 +242,17 @@ config PM_OPS
bool
depends on PM_SLEEP || PM_RUNTIME
default y
+
+config PM_OPP
+ bool "Enable Operating Performance Point(OPP) Layer library"
+ depends on PM
+ ---help---
+ SOCs have a standard set of tuples consisting of frequency and
+ voltage pairs that the device will support per voltage domain. This
+ is called Operating Performance Point or OPP. The actual definitions
+ of OPP varies over silicon within the same family of devices.
+
+ OPP layer organizes the data internally using device pointers
+ representing individual voltage domains and provides SOC
+ implementations a ready to use framework to manage OPPs.
+ For more information, read <file:Documentation/power/opp.txt>
--
1.6.3.3
^ permalink raw reply related
* [PATCH v7] power: introduce library for device-specific OPPs
From: Nishanth Menon @ 2010-10-08 3:02 UTC (permalink / raw)
To: linux-pm, lkml; +Cc: l-o, l-a, Rafael, Paul
In-Reply-To: <[PATCH] power: introduce library for device-specific OPPs>
SoCs have a standard set of tuples consisting of frequency and
voltage pairs that the device will support per voltage domain. These
are called Operating Performance Points or OPPs. The actual
definitions of OPP varies over silicon versions. For a specific domain,
we can have a set of {frequency, voltage} pairs. As the kernel boots
and more information is available, a default set of these are activated
based on the precise nature of device. Further on operation, based on
conditions prevailing in the system (such as temperature), some OPP
availability may be temporarily controlled by the SoC frameworks.
To implement an OPP, some sort of power management support is necessary
hence this library depends on CONFIG_PM.
Contributions include:
Sanjeev Premi for the initial concept:
http://patchwork.kernel.org/patch/50998/
Kevin Hilman for converting original design to device-based
Kevin Hilman and Paul Walmsey for cleaning up many of the function
abstractions, improvements and data structure handling
Romit Dasgupta for using enums instead of opp pointers
Thara Gopinath, Eduardo Valentin and Vishwanath BS for fixes and
cleanups.
Linus Walleij for recommending this layer be made generic for usage
in other architectures beyond OMAP and ARM.
Mark Brown, Andrew Morton, Rafael J Wysocki, Paul E McKenney for valuable
improvements.
Discussions and comments from:
http://marc.info/?l=linux-omap&m=126033945313269&w=2
http://marc.info/?l=linux-omap&m=125482970102327&w=2
http://marc.info/?t=125809247500002&r=1&w=2
http://marc.info/?l=linux-omap&m=126025973426007&w=2
http://marc.info/?t=128152609200064&r=1&w=2
http://marc.info/?t=128468723000002&r=1&w=2
incorporated.
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Phil Carmody <ext-phil.2.carmody@nokia.com>
Cc: Roberto Granados Dorado <x0095451@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Tero Kristo <Tero.Kristo@nokia.com>
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath BS <vishwanath.bs@ti.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
V7:
removed pr_fmt and used dev_err/warn instead of pr_xx family where
possible
replaced out1 label with unlock to make it readable
Accepted a offline suggestion to use IS_ERR_OR_NULL to replace
!var || IS_ERR(var) check in find_device_opp, opp_get_voltage &
opp_get_freq
V6: https://patchwork.kernel.org/patch/235591/
mutexes reduced to a single one. dev_opp_list_lock now protects
both the devices and the opp lists, doc updated accordingly.
fixed opp_add removed an irrelevant find_device_opp, used IS_ERR to
check pointer
fixed updater routines to remove unnecessary reader operations.
comments from v5 not included in v6:
- synchronize_rcu() is not needed after list_add_rcu as pointed by
Paul in http://marc.info/?l=linux-omap&m=128535708720191&w=2
I have retained it's usage after list_replace_rcu as with v4.
- Temporary release of mutex in opp_add under if (IS_ERR(dev_opp)) {
Rationale:
If two parallel calls to opp_add on the same device node which
is not yet added in the list can cause data structure integrity
issues. For example:
c1: holds mutex dev_opp_list_lock
c2: starts and is blocked on dev_opp_list_lock mutex here
dev_opp = find_device_opp(dev); [c1 in progress here]
if (IS_ERR(dev_opp)) {
If c1 releases dev_opp_list_lock here, c2 can proceed
to call find_device_opp which will return error and will
cause following allocation to take place for same device
node.
dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
This is undesirable as it will result in an additional node added
for the same device (since the device is the same, c1 should have
added the new node and c2 should have just added an opp).
Since the actual addition of a device node by itself is rare,
kzalloc is a tiny penalty to pay for integrity of the data structure.
The other option being to move the kzalloc before the mutex locking,
but, that will cause dev_opp allocation overhead for every opp
addition.
All other comments have been incorporated.
Tested with cpufreq on SDP3630 (TI OMAP3630) with lockdep debugging to
catch races.
V5: https://patchwork.kernel.org/patch/223272/
opp pointers were being passed to callers outside rcu locks, this
causes the pointers to be potentially invalid between calls if
opp_enable/disable calls take place.
The solution for this cannot be reference counters either, as
opp pointer without control of opp library and rcu locks are
completely untrustworthy. The better approach is to enforce
restrictions on callers of query and retrieval functions to wrap
the relevant parts under rcu locks. This allows for tremendous
flexibility in the way opp libraries can be used as the users
can optimize their implementation based on the requirements.
NOTE: find_device_opp is implicitly wrapped as a result.
(ref, v4 comments)
One more side-effect has been that the opp_enable and disable
functions changed their prototypes to make it a little more easier
for the users to use them without having to get the pointers before
hand, as well as do the functionality that is being provided currently
as well.
opp_init_cpufreq_table now returns int and result of operation for
callers to adequately handle their error conditions.
pr_fmt is being used instead of duplicating "%s" .. __func__ with
every pr_xxx call.
Documentation update to reflect these.
Sample usage:
http://pastebin.mozilla.org/802375: cleanups for omap pm layer
http://pastebin.mozilla.org/802374: omap opp initialization
V4: http://marc.info/?t=128533285000002&r=1&w=2
Cc list trimmed to just the MLs.
RCU implementation - thanks for the pointers Rafael
re-tested on OMAP3630 with lock debugging enabled including cpufreq,
idle paths and "exception cases - enable/disable".
available_opp_count removed as it complicated the updates altogether
+ the usage latencies are not too high given small lists.
In removed list_reverse usage as rcu has no list reverse equivalents
+ searching either direction has no real difference when the list
is ordered.
change in protos for get_{voltage,frequency} - const removed from
parameter as rcu_dereference causes build warnings
introduced opp_set_availability helper to wrap common code between
opp_{enable,disable} - leaving these as is as they are more readable
from usage perspective + these are not meant to be used in hot paths
anyways.
Header guard __ASM_OPP_H replaced with __LINUX_OPP_H__ for opp.h
V3: https://patchwork.kernel.org/patch/200382/
Bunch of documentation update based on feedback
removed opp_def - opp_add enables the opp by default
lock usage optimization
Sample usage:
http://pastebin.mozilla.org/794786 -> cleanups for OMAP power
http://pastebin.mozilla.org/794787 -> Sample OPP initialization for OMAP
V2: https://patchwork.kernel.org/patch/189532/
Incorporated review comments from v1. major changes being:
$subject change to reflect this is for power.
Documentation revamp and including it in the patch :)
OPP_DEF removed - lets introduce this if needed or leave it to
SOC frameworks to organize code as needed.
Rename of enable to available to better reflect the intent
few fixes and typos
Introduced mutex based locking for controlling access to list
modification (note: query functions are still unsafe- rationale
in the patch below)
A new home for opp.c in drivers/base/power (moved from lib/)
A few optimization in function flow and additional error checks
added to exposed functions
offline aligned with Kevin for cleaning up the copyrights
V1: http://marc.info/?t=128468723000002&r=1&w=2
Documentation/power/00-INDEX | 2 +
Documentation/power/opp.txt | 373 +++++++++++++++++++++++++
drivers/base/power/Makefile | 1 +
drivers/base/power/opp.c | 626 ++++++++++++++++++++++++++++++++++++++++++
include/linux/opp.h | 105 +++++++
kernel/power/Kconfig | 14 +
6 files changed, 1121 insertions(+), 0 deletions(-)
create mode 100644 Documentation/power/opp.txt
create mode 100644 drivers/base/power/opp.c
create mode 100644 include/linux/opp.h
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index fb742c2..45e9d4a 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -14,6 +14,8 @@ interface.txt
- Power management user interface in /sys/power
notifiers.txt
- Registering suspend notifiers in device drivers
+opp.txt
+ - Operating Performance Point library
pci.txt
- How the PCI Subsystem Does Power Management
pm_qos_interface.txt
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
new file mode 100644
index 0000000..b309e30
--- /dev/null
+++ b/Documentation/power/opp.txt
@@ -0,0 +1,373 @@
+*=============*
+* OPP Library *
+*=============*
+
+Contents
+--------
+1. Introduction
+2. Initial OPP List Registration
+3. OPP Search Functions
+4. OPP Availability Control Functions
+5. OPP Data Retrieval Functions
+6. Cpufreq Table Generation
+7. Data Structures
+
+1. Introduction
+===============
+Complex SoCs of today consists of a multiple sub-modules working in conjunction.
+In an operational system executing varied use cases, not all modules in the SoC
+need to function at their highest performing frequency all the time. To
+facilitate this, sub-modules in a SoC are grouped into domains, allowing some
+domains to run at lower voltage and frequency while other domains are loaded
+more. The set of discrete tuples consisting of frequency and voltage pairs that
+the device will support per domain are called Operating Performance Points or
+OPPs.
+
+OPP library provides a set of helper functions to organize and query the OPP
+information. The library is located in drivers/base/power/opp.c and the header
+is located in include/linux/opp.h. OPP library can be enabled by enabling
+CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
+CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+optionally boot at a certain OPP without needing cpufreq.
+
+Typical usage of the OPP library is as follows:
+(users) -> registers a set of default OPPs -> (library)
+SoC framework -> modifies on required cases certain OPPs -> OPP layer
+ -> queries to search/retrieve information ->
+
+OPP layer expects each domain to be represented by a unique device pointer. SoC
+framework registers a set of initial OPPs per device with the OPP layer. This
+list is expected to be an optimally small number typically around 5 per device.
+This initial list contains a set of OPPs that the framework expects to be safely
+enabled by default in the system.
+
+Note on OPP Availability:
+------------------------
+As the system proceeds to operate, SoC framework may choose to make certain
+OPPs available or not available on each device based on various external
+factors. Example usage: Thermal management or other exceptional situations where
+SoC framework might choose to disable a higher frequency OPP to safely continue
+operations until that OPP could be re-enabled if possible.
+
+OPP library facilitates this concept in it's implementation. The following
+operational functions operate only on available opps:
+opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
+and opp_init_cpufreq_table
+
+opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for opp_enable/disable functions to make an opp available as required.
+
+WARNING: Users of OPP library should refresh their availability count using
+get_opp_count if opp_enable/disable functions are invoked for a device, the
+exact mechanism to trigger these or the notification mechanism to other
+dependent subsystems such as cpufreq are left to the discretion of the SoC
+specific framework which uses the OPP library. Similar care needs to be taken
+care to refresh the cpufreq table in cases of these operations.
+
+WARNING on OPP List locking mechanism:
+-------------------------------------------------
+OPP library uses RCU for exclusivity. RCU allows the query functions to operate
+in multiple contexts and this synchronization mechanism is optimal for a read
+intensive operations on data structure as the OPP library caters to.
+
+To ensure that the data retrieved are sane, the users such as SoC framework
+should ensure that the section of code operating on OPP queries are locked
+using RCU read locks. The opp_find_freq_{exact,ceil,floor},
+opp_get_{voltage, freq, opp_count} fall into this category.
+
+opp_{add,enable,disable} are updaters which use mutex and implement it's own
+RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+mutex to implment RCU updater strategy. These functions should *NOT* be called
+under RCU locks and other contexts that prevent blocking functions in RCU or
+mutex operations from working.
+
+2. Initial OPP List Registration
+================================
+The SoC implementation calls opp_add function iteratively to add OPPs per
+device. It is expected that the SoC framework will register the OPP entries
+optimally- typical numbers range to be less than 5. The list generated by
+registering the OPPs is maintained by OPP library throughout the device
+operation. The SoC framework can subsequently control the availability of the
+OPPs dynamically using the opp_enable / disable functions.
+
+opp_add - Add a new OPP for a specific domain represented by the device pointer.
+ The OPP is defined using the frequency and voltage. Once added, the OPP
+ is assumed to be available and control of it's availability can be done
+ with the opp_enable/disable functions. OPP library internally stores
+ and manages this information in the opp struct. This function may be
+ used by SoC framework to define a optimal list as per the demands of
+ SoC usage environment.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_add(mpu_dev, 1000000, 900000);
+ if (!r) {
+ pr_err("%s: unable to register mpu opp(%d)\n", r);
+ goto no_cpufreq;
+ }
+ /* Do cpufreq things */
+ no_cpufreq:
+ /* Do remaining things */
+ }
+
+3. OPP Search Functions
+=======================
+High level framework such as cpufreq operates on frequencies. To map the
+frequency back to the corresponding OPP, OPP library provides handy functions
+to search the OPP list that OPP library internally manages. These search
+functions return the matching pointer representing the opp if a match is
+found, else returns error. These errors are expected to be handled by standard
+error checks such as IS_ERR() and appropriate actions taken by the caller.
+
+opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+ availability. This function is especially useful to enable an OPP which
+ is not available by default.
+ Example: In a case when SoC framework detects a situation where a
+ higher frequency could be made available, it can use this function to
+ find the OPP prior to call the opp_enable to actually make it available.
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* dont operate on the pointer.. just do a sanity check.. */
+ if (IS_ERR(opp)) {
+ pr_err("frequency not disabled!\n");
+ /* trigger appropriate actions.. */
+ } else {
+ opp_enable(dev,1000000000);
+ }
+
+ NOTE: This is the only search function that operates on OPPs which are
+ not available.
+
+opp_find_freq_floor - Search for an available OPP which is *at most* the
+ provided frequency. This function is useful while searching for a lesser
+ match OR operating on OPP information in the order of decreasing
+ frequency.
+ Example: To find the highest opp for a device:
+ freq = ULONG_MAX;
+ rcu_read_lock();
+ opp_find_freq_floor(dev, &freq);
+ rcu_read_unlock();
+
+opp_find_freq_ceil - Search for an available OPP which is *at least* the
+ provided frequency. This function is useful while searching for a
+ higher match OR operating on OPP information in the order of increasing
+ frequency.
+ Example 1: To find the lowest opp for a device:
+ freq = 0;
+ rcu_read_lock();
+ opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ Example 2: A simplified implementation of a SoC cpufreq_driver->target:
+ soc_cpufreq_target(..)
+ {
+ /* Do stuff like policy checks etc. */
+ /* Find the best frequency match for the req */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ if (!IS_ERR(opp))
+ soc_switch_to_freq_voltage(freq);
+ else
+ /* do something when we cant satisfy the req */
+ /* do other stuff */
+ }
+
+4. OPP Availability Control Functions
+=====================================
+A default OPP list registered with the OPP library may not cater to all possible
+situation. The OPP library provides a set of functions to modify the
+availability of a OPP within the OPP list. This allows SoC frameworks to have
+fine grained dynamic control of which sets of OPPs are operationally available.
+These functions are intended to *temporarily* remove an OPP in conditions such
+as thermal considerations (e.g. don't use OPPx until the temperature drops).
+
+WARNING: Do not use these functions in interrupt context.
+
+opp_enable - Make a OPP available for operation.
+ Example: Lets say that 1GHz OPP is to be made available only if the
+ SoC temperature is lower than a certain threshold. The SoC framework
+ implementation might choose to do something as follows:
+ if (cur_temp < temp_low_thresh) {
+ /* Enable 1GHz if it was disabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_enable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+opp_disable - Make an OPP to be not available for operation
+ Example: Lets say that 1GHz OPP is to be disabled if the temperature
+ exceeds a threshold value. The SoC framework implementation might
+ choose to do something as follows:
+ if (cur_temp > temp_high_thresh) {
+ /* Disable 1GHz if it was enabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, true);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_disable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+5. OPP Data Retrieval Functions
+===============================
+Since OPP library abstracts away the OPP information, a set of functions to pull
+information from the OPP structure is necessary. Once an OPP pointer is
+retrieved using the search functions, the following functions can be used by SoC
+framework to retrieve the information represented inside the OPP layer.
+
+opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+ Example: At a cpufreq transition to a different frequency, SoC
+ framework requires to set the voltage represented by the OPP using
+ the regulator framework to the Power Management chip providing the
+ voltage.
+ soc_switch_to_freq_voltage(freq)
+ {
+ /* do things */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ v = opp_get_voltage(opp);
+ rcu_read_unlock();
+ if (v)
+ regulator_set_voltage(.., v);
+ /* do other things */
+ }
+
+opp_get_freq - Retrieve the freq represented by the opp pointer.
+ Example: Lets say the SoC framework uses a couple of helper functions
+ we could pass opp pointers instead of doing additional parameters to
+ handle quiet a bit of data parameters.
+ soc_cpufreq_target(..)
+ {
+ /* do things.. */
+ max_freq = ULONG_MAX;
+ rcu_read_lock();
+ max_opp = opp_find_freq_floor(dev,&max_freq);
+ requested_opp = opp_find_freq_ceil(dev,&freq);
+ if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
+ r = soc_test_validity(max_opp, requested_opp);
+ rcu_read_unlock();
+ /* do other things */
+ }
+ soc_test_validity(..)
+ {
+ if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+ return -EINVAL;
+ if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+ return -EINVAL;
+ /* do things.. */
+ }
+
+opp_get_opp_count - Retrieve the number of available opps for a device
+ Example: Lets say a co-processor in the SoC needs to know the available
+ frequencies in a table, the main processor can notify as following:
+ soc_notify_coproc_available_frequencies()
+ {
+ /* Do things */
+ rcu_read_lock();
+ num_available = opp_get_opp_count(dev);
+ speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
+ /* populate the table in increasing order */
+ freq = 0;
+ while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+ speeds[i] = freq;
+ freq++;
+ i++;
+ }
+ rcu_read_unlock();
+
+ soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
+ /* Do other things */
+ }
+
+6. Cpufreq Table Generation
+===========================
+opp_init_cpufreq_table - cpufreq framework typically is initialized with
+ cpufreq_frequency_table_cpuinfo which is provided with the list of
+ frequencies that are available for operation. This function provides
+ a ready to use conversion routine to translate the OPP layer's internal
+ information about the available frequencies into a format readily
+ providable to cpufreq.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_init_cpufreq_table(dev, &freq_table);
+ if (!r)
+ cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ /* Do other things */
+ }
+
+ NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
+ addition to CONFIG_PM as power management feature is required to
+ dynamically scale voltage and frequency in a system.
+
+7. Data Structures
+==================
+Typically an SoC contains multiple voltage domains which are variable. Each
+domain is represented by a device pointer. The relationship to OPP can be
+represented as follows:
+SoC
+ |- device 1
+ | |- opp 1 (availability, freq, voltage)
+ | |- opp 2 ..
+ ... ...
+ | `- opp n ..
+ |- device 2
+ ...
+ `- device m
+
+OPP library maintains a internal list that the SoC framework populates and
+accessed by various functions as described above. However, the structures
+representing the actual OPPs and domains are internal to the OPP library itself
+to allow for suitable abstraction reusable across systems.
+
+struct opp - The internal data structure of OPP library which is used to
+ represent an OPP. In addition to the freq, voltage, availability
+ information, it also contains internal book keeping information required
+ for the OPP library to operate on. Pointer to this structure is
+ provided back to the users such as SoC framework to be used as a
+ identifier for OPP in the interactions with OPP layer.
+
+ WARNING: The struct opp pointer should not be parsed or modified by the
+ users. The defaults of for an instance is populated by opp_add, but the
+ availability of the OPP can be modified by opp_enable/disable functions.
+
+struct device - This is used to identify a domain to the OPP layer. The
+ nature of the device and it's implementation is left to the user of
+ OPP library such as the SoC framework.
+
+Overall, in a simplistic view, the data structure operations is represented as
+following:
+
+Initialization / modification:
+ +-----+ /- opp_enable
+opp_add --> | opp | <-------
+ | +-----+ \- opp_disable
+ \-------> domain_info(device)
+
+Search functions:
+ /-- opp_find_freq_ceil ---\ +-----+
+domain_info<---- opp_find_freq_exact -----> | opp |
+ \-- opp_find_freq_floor ---/ +-----+
+
+Retrieval functions:
++-----+ /- opp_get_voltage
+| opp | <---
++-----+ \- opp_get_freq
+
+domain_info <- opp_get_opp_count
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index cbccf9a..abe46ed 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_OPS) += generic_ops.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
+obj-$(CONFIG_PM_OPP) += opp.o
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
new file mode 100644
index 0000000..abc5be5
--- /dev/null
+++ b/drivers/base/power/opp.c
@@ -0,0 +1,626 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/opp.h>
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ * |- device 1 (represents voltage domain 1)
+ * | |- opp 1 (availability, freq, voltage)
+ * | |- opp 2 ..
+ * ... ...
+ * | `- opp n ..
+ * |- device 2 (represents the next voltage domain)
+ * ...
+ * `- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct opp - Generic OPP description structure
+ * @node: opp list node. The nodes are maintained throughout the lifetime
+ * of boot. It is expected only an optimal set of OPPs are
+ * added to the library by the SoC framework.
+ * RCU usage: opp list is traversed with RCU locks. node
+ * modification is possible realtime, hence the modifications
+ * are protected by the dev_opp_list_lock for integrity.
+ * IMPORTANT: the opp nodes should be maintained in increasing
+ * order.
+ * @available: true/false - marks if this OPP as available or not
+ * @rate: Frequency in hertz
+ * @u_volt: Nominal voltage in microvolts corresponding to this OPP
+ * @dev_opp: points back to the device_opp struct this opp belongs to
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct opp {
+ struct list_head node;
+
+ bool available;
+ unsigned long rate;
+ unsigned long u_volt;
+
+ struct device_opp *dev_opp;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node: list node - contains the devices with OPPs that
+ * have been registered. Nodes once added are not modified in this
+ * list.
+ * RCU usage: nodes are not modified in the list of device_opp,
+ * however addition is possible and is secured by dev_opp_list_lock
+ * @dev: device pointer
+ * @opp_list: list of opps
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library
+ */
+struct device_opp {
+ struct list_head node;
+
+ struct device *dev;
+ struct list_head opp_list;
+};
+
+/*
+ * The root of the list of all devices. All device_opp structures branch off
+ * from here, with each device_opp containing the list of opp it supports in
+ * various states of availability.
+ */
+static LIST_HEAD(dev_opp_list);
+/* Lock to allow exclusive modification to the device and opp lists */
+static DEFINE_MUTEX(dev_opp_list_lock);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev: device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device. Does a RCU
+ * reader operation to grab the pointer needed.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * -EINVAL based on type of error.
+ *
+ * Locking: This function must be called under rcu_read_lock(). device_opp
+ * is a RCU protected pointer. This means that device_opp is valid as long
+ * as we are under RCU lock.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+ if (unlikely(IS_ERR_OR_NULL(dev))) {
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
+ if (tmp_dev_opp->dev == dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+
+ return dev_opp;
+}
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * @opp: opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_voltage(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long v = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ else
+ v = tmp_opp->u_volt;
+
+ return v;
+}
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * @opp: opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_freq(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long f = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters being passed\n", __func__);
+ else
+ f = tmp_opp->rate;
+
+ return f;
+}
+
+/**
+ * opp_get_opp_count() - Get number of opps available in the opp list
+ * @dev: device for which we do this operation
+ *
+ * This function returns the number of available opps if there are any,
+ * else returns 0 if none or the corresponding error value.
+ *
+ * Locking: This function must be called under rcu_read_lock(). This function
+ * internally references two RCU protected structures: device_opp and opp which
+ * are safe as long as we are under a common RCU locked section.
+ */
+int opp_get_opp_count(struct device *dev)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp;
+ int count = 0;
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ dev_warn(dev, "%s: device not found in list\n", __func__);
+ return PTR_ERR(dev_opp);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available)
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * opp_find_freq_exact() - search for an exact frequency
+ * @dev: device for which we do this operation
+ * @freq: frequency to search for
+ * @is_available: true/false - match for available opp
+ *
+ * Searches for exact match in the opp list and returns pointer to the matching
+ * opp if found, else returns ERR_PTR in case of error and should be handled
+ * using IS_ERR.
+ *
+ * Note: available is a modifier for the search. if available=true, then the
+ * match is for exact matching frequency and is available in the stored OPP
+ * table. if false, the match is for exact frequency which is not available.
+ *
+ * This provides a mechanism to enable an opp which is not available currently
+ * or the opposite as well.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ int r = PTR_ERR(dev_opp);
+ dev_err(dev, "%s: device not found in list(%d)\n", __func__, r);
+ return ERR_PTR(r);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available == available &&
+ temp_opp->rate == freq) {
+ opp = temp_opp;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching ceil *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid param. freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available && temp_opp->rate >= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_floor() - Search for a rounded floor freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching floor *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid param. freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available) {
+ /* go to the next node, before choosing prev */
+ if (temp_opp->rate > *freq)
+ break;
+ else
+ opp = temp_opp;
+ }
+ }
+ if (!IS_ERR(opp))
+ *freq = opp->rate;
+
+ return opp;
+}
+
+/**
+ * opp_add() - Add an OPP table from a table definitions
+ * @dev: device for which we do this operation
+ * @freq: Frequency in Hz for this OPP
+ * @u_volt: Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+ struct device_opp *dev_opp = NULL;
+ struct opp *opp, *new_opp;
+ struct list_head *head;
+
+ /* allocate new OPP node */
+ new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to allocate new opp node\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Check for existing list for 'dev' */
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ /*
+ * Allocate a new device OPP table. In the infrequent case
+ * where a new device is needed to be added, we pay this
+ * penalty.
+ */
+ dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+ if (!dev_opp) {
+ mutex_unlock(&dev_opp_list_lock);
+ kfree(new_opp);
+ dev_warn(dev, "%s: Unable to alloc device structure\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ dev_opp->dev = dev;
+ INIT_LIST_HEAD(&dev_opp->opp_list);
+
+ /* Secure the device list modification */
+ list_add_rcu(&dev_opp->node, &dev_opp_list);
+ }
+
+ /* populate the opp table */
+ new_opp->dev_opp = dev_opp;
+ new_opp->rate = freq;
+ new_opp->u_volt = u_volt;
+ new_opp->available = true;
+
+ /* Insert new OPP in order of increasing frequency */
+ head = &dev_opp->opp_list;
+ list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+ if (new_opp->rate < opp->rate)
+ break;
+ else
+ head = &opp->node;
+ }
+
+ list_add_rcu(&new_opp->node, head);
+ mutex_unlock(&dev_opp_list_lock);
+
+ return 0;
+}
+
+/**
+ * opp_set_availability() - helper to set the availability of an opp
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to modify availability
+ * @availability_req: availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int opp_set_availability(struct device *dev, unsigned long freq,
+ bool availability_req)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+ struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+ int r = 0;
+
+ /* keep the node allocated */
+ new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to allocate opp\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Find the device_opp */
+ list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+ if (dev == tmp_dev_opp->dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+ if (IS_ERR(dev_opp)) {
+ r = PTR_ERR(dev_opp);
+ dev_warn(dev, "%s: Unable to find device in list\n", __func__);
+ goto unlock;
+ }
+
+ /* Do we have the frequency? */
+ list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+ if (tmp_opp->rate == freq) {
+ opp = tmp_opp;
+ break;
+ }
+ }
+ if (IS_ERR(opp)) {
+ r = PTR_ERR(opp);
+ goto unlock;
+ }
+
+ /* Is update really needed? */
+ if (opp->available == availability_req)
+ goto unlock;
+ /* copy the old data over */
+ *new_opp = *opp;
+
+ /* plug in new node */
+ new_opp->available = availability_req;
+
+ list_replace_rcu(&opp->node, &new_opp->node);
+ mutex_unlock(&dev_opp_list_lock);
+ synchronize_rcu();
+
+ /* clean up old opp */
+ new_opp = opp;
+ goto out;
+
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+out:
+ kfree(new_opp);
+ return r;
+}
+
+/**
+ * opp_enable() - Enable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to enable
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value. It is meant to be used for users an OPP available
+ * after being temporarily made unavailable with opp_disable.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_enable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, true);
+}
+
+/**
+ * opp_disable() - Disable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to disable
+ *
+ * Disables a provided opp. If the operation is valid, this returns
+ * 0, else the corresponding error value. It is meant to be a temporary
+ * control by users to make this OPP not available until the circumstances are
+ * right to make it available again (with a call to opp_enable).
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_disable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, false);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/**
+ * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev: device for which we do this operation
+ * @table: Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * To simplify the logic, we pretend we are updater and hold relevant mutex here
+ * Callers should ensure that this function is *NOT* called under RCU protection
+ * or in contexts where mutex locking cannot be used.
+ */
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ struct device_opp *dev_opp;
+ struct opp *opp;
+ struct cpufreq_frequency_table *freq_table;
+ int i = 0;
+
+ /* Pretend as if I am an updater */
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Unable to find device in list\n", __func__);
+ return PTR_ERR(dev_opp);
+ }
+
+ freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+ (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+ if (!freq_table) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Failed to allocate frequency table\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ list_for_each_entry(opp, &dev_opp->opp_list, node) {
+ if (opp->available) {
+ freq_table[i].index = i;
+ freq_table[i].frequency = opp->rate / 1000;
+ i++;
+ }
+ }
+ mutex_unlock(&dev_opp_list_lock);
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *table = &freq_table[0];
+
+ return 0;
+}
+#endif /* CONFIG_CPU_FREQ */
diff --git a/include/linux/opp.h b/include/linux/opp.h
new file mode 100644
index 0000000..5449945
--- /dev/null
+++ b/include/linux/opp.h
@@ -0,0 +1,105 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+
+struct opp;
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long opp_get_voltage(struct opp *opp);
+
+unsigned long opp_get_freq(struct opp *opp);
+
+int opp_get_opp_count(struct device *dev);
+
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available);
+
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
+
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
+
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
+
+int opp_enable(struct device *dev, unsigned long freq);
+
+int opp_disable(struct device *dev, unsigned long freq);
+
+#else
+static inline unsigned long opp_get_voltage(struct opp *opp)
+{
+ return 0;
+}
+
+static inline unsigned long opp_get_freq(struct opp *opp)
+{
+ return 0;
+}
+
+static inline int opp_get_opp_count(struct device *dev)
+{
+ return 0;
+}
+
+static inline struct opp *opp_find_freq_exact(struct device *dev,
+ unsigned long freq, bool available)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_floor(struct device *dev,
+ unsigned long *freq)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_ceil(struct device *dev,
+ unsigned long *freq)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline int opp_add(struct device *dev, unsigned long freq,
+ unsigned long u_volt)
+{
+ return -EINVAL;
+}
+
+static inline int opp_enable(struct device *dev, unsigned long freq)
+{
+ return 0;
+}
+
+static inline int opp_disable(struct device *dev, unsigned long freq)
+{
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table);
+#else
+static inline int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_CPU_FREQ */
+
+#endif /* __LINUX_OPP_H__ */
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ca6066a..634eab6 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -242,3 +242,17 @@ config PM_OPS
bool
depends on PM_SLEEP || PM_RUNTIME
default y
+
+config PM_OPP
+ bool "Enable Operating Performance Point(OPP) Layer library"
+ depends on PM
+ ---help---
+ SOCs have a standard set of tuples consisting of frequency and
+ voltage pairs that the device will support per voltage domain. This
+ is called Operating Performance Point or OPP. The actual definitions
+ of OPP varies over silicon within the same family of devices.
+
+ OPP layer organizes the data internally using device pointers
+ representing individual voltage domains and provides SOC
+ implementations a ready to use framework to manage OPPs.
+ For more information, read <file:Documentation/power/opp.txt>
--
1.6.3.3
^ permalink raw reply related
* Re: [RFC v2 PATCH 1/1] PCI: override BIOS/firmware resource allocation
From: Bjorn Helgaas @ 2010-10-07 21:41 UTC (permalink / raw)
To: Ram Pai
Cc: linux-pci, linux-kernel, clemens, Yinghai Lu, Jesse Barnes,
Linus Torvalds
In-Reply-To: <20101007204213.GA4461@ram-laptop>
On Thursday, October 07, 2010 02:42:13 pm Ram Pai wrote:
> On Wed, Oct 06, 2010 at 10:13:02PM -0600, Bjorn Helgaas wrote:
> > On Wed, Oct 06, 2010 at 05:30:41PM -0700, Ram Pai wrote:
> > > On Wed, Oct 06, 2010 at 05:39:53PM -0600, Bjorn Helgaas wrote:
> > > > On Wed, Oct 06, 2010 at 03:58:34PM -0700, Ram Pai wrote:
> > > > > PCI: override BIOS/firmware memory resource allocation
> > > > > through command line parameters
> > > > >
> > > > > Platforms that are unaware of SRIOV BARs fail to allocate MMIO
> > > > > resources to SRIOV PCIe devices. Hence on such platforms the
> > > > > OS fails to enable SRIOV.
> > > > > Some platforms where BIOS/uEFI resource allocations conflict
> > > > > the conflicting devices are disabled.
> > > > >
> > > > > Ideally we would want the OS to detect and fix automatically
> > > > > such problems and conflicts. However previous attempts to do so
> > > > > have led to regression on legacy platforms.
> > > >
> > > > I'm sorry to be a nay-sayer, but I think we just haven't tried hard
> > > > enough. Our ACPI/PCI/e820 resource management is not well integrated,
> > > > and I suspect if we straightened that out, we could avoid some of the
> > > > regressions we saw with previous attempts.
> > >
> > > Can you be more specific as to what can be done to fix it automatically?
> > >
> > > Neither accepting this approach nor telling what needs to be straightened out
> > > to automatically fix all the systems out there, is just a deadend.
> >
> > Yeah, I guess that wasn't really fair, sorry. And keep in mind that I'm
> > not the PCI maintainer, so these are just my opinions, nothing like an
> > official "nack."
> >
> > I did look at this dmesg log from the thread you referenced:
> > http://marc.info/?l=linux-kernel&m=127178918128740&w=2
> > but it looks to me like we just completely botched it. I don't see an
> > SRIOV device or anything else that didn't have resources, so as far as I
> > can tell, we started with working resource assignments from the BIOS,
> > threw them away, and started over from scratch. We failed because we
> > tried to assign I/O port space to bridges with nothing behind them, and
> > there was nothing left by the time we got to the 0000:09:04.0 device
> > that actually *did* need the space.
>
> hmm.. is that possible? Yinghai's patch sized the resource requirement of each
> of the bridges, before actually allocating them. Which means a bridge with
> no device behind it would not get any i/o space.
Here's what I see in the dmesg log referenced above:
ACPI: PCI Root Bridge [PCI0] (0000:00)
pci_root PNP0A08:00: host bridge window [io 0x0000-0x0cf7]
pci_root PNP0A08:00: host bridge window [io 0x0d00-0xffff]
pci 0000:00:1c.0: PCI bridge to [bus 04-09]
pci 0000:00:1c.0: bridge window [io 0xd000-0xdfff]
pci 0000:04:00.0: PCI bridge to [bus 05-09]
pci 0000:04:00.0: bridge window [io 0xd000-0xdfff]
pci 0000:05:01.0: PCI bridge to [bus 08-09]
pci 0000:05:01.0: bridge window [io 0xd000-0xdfff]
pci 0000:08:00.0: PCI bridge to [bus 09-09]
pci 0000:08:00.0: bridge window [io 0xd000-0xdfff]
pci 0000:09:04.0: found [13f6:8788] class 000401 header type 00
pci 0000:09:04.0: reg 10: [io 0xd800-0xd8ff]
pci 0000:05:02.0: PCI bridge to [bus 07-07]
pci 0000:05:02.0: bridge window [io 0xf000-0x0000] (disabled)
pci 0000:05:03.0: PCI bridge to [bus 06-06]
pci 0000:05:03.0: bridge window [io 0xf000-0x0000] (disabled)
The above is the state as we got it from BIOS. Despite all the bridges,
09:04.0 is the only device below the 00:1c.0 bridge, and it requires only
0x100 I/O ports.
There are no devices on buses 06 (below 05:03.0) or 07 (below 05:02.0).
I didn't look at Yinghai's patch to figure out *why*, but it sure looks like
we released the 09:04.0 space, then tried to assign 0x2000 ports to 05:01.0
(which needs 0x100 and had 0x1000 originally), 0x1000 to 05:02.0 (which needs
none), and 0x1000 to 05:03.0 (which also needs none):
PCI: No. 3 try to assign unassigned res
release child resource [io 0xd800-0xd8ff]
pci 0000:08:00.0: resource 7 [io 0xd000-0xdfff] released
pci 0000:04:00.0: BAR 7: can't assign io (size 0x4000)
pci 0000:05:01.0: BAR 7: can't assign io (size 0x2000)
pci 0000:05:02.0: BAR 7: can't assign io (size 0x1000)
pci 0000:05:03.0: BAR 7: can't assign io (size 0x1000)
pci 0000:08:00.0: BAR 7: can't assign io (size 0x1000)
pci 0000:09:04.0: BAR 0: can't assign io (size 0x100)
I think there are at least two things wrong here:
1) We rearranged things when we didn't need to, and
2) We assigned I/O ports to bridge that didn't need them
Neither one is a terrible problem, so I think it's better to just fix
them than to add a special alternate path and a kernel parameter to
enable it.
> > > The choice is between
> > > (a) an automated patch with the risk of regressing some platforms.
> > > (b) an semi-automated patch that does not regress *any* platform,
> > > with the ability to fix platforms that are currently broken.
> > > (c) status quo, which means broken platforms continue to be so.
> > >
> > > I thought the initial proposal was to use (b), with the long
> > > term goal of fixing it automatically, assuming that it is even possible.
> > >
> > > Let me know if that is *not* the goal and I will change directions.
> >
> > *My* goal is that a user would never need a kernel option except to help
> > debug kernel problems. I think of an option like "pci=override" as a
> > band-aid that covers up a kernel problem without really fixing it, so I
> > guess my choice would be (a). Yes, there's a risk of regression, and we
> > have to do everything we can to avoid it. But the result is a more
> > usable system.
>
> Ok. I think we agree with your goal, but the disagreement is on the approach.
> You want to take one big leap, whereas the consensus I heard in earlier
> threads was that we need to take baby steps.
We need baby steps in terms of a series of tiny patches. I'm not yet
convinced that we need to add a "mostly-working" alternate path and
make the user figure out whether to use it. That makes things more
complicated and reduces testing coverage.
Bjorn
^ permalink raw reply
* [Qemu-devel] Re: [patch uq/master 7/8] MCE: Relay UCR MCE to guest
From: Huang Ying @ 2010-10-08 2:50 UTC (permalink / raw)
To: Marcelo Tosatti
Cc: Dean Nelson, Hidetoshi Seto, qemu-devel@nongnu.org,
kvm@vger.kernel.org
In-Reply-To: <20101006160531.GB4277@amt.cnet>
On Thu, 2010-10-07 at 00:05 +0800, Marcelo Tosatti wrote:
> On Wed, Oct 06, 2010 at 10:58:36AM +0900, Hidetoshi Seto wrote:
> > I got some more question:
> >
> > (2010/10/05 3:54), Marcelo Tosatti wrote:
> > > Index: qemu/target-i386/cpu.h
> > > ===================================================================
> > > --- qemu.orig/target-i386/cpu.h
> > > +++ qemu/target-i386/cpu.h
> > > @@ -250,16 +250,32 @@
> > > #define PG_ERROR_RSVD_MASK 0x08
> > > #define PG_ERROR_I_D_MASK 0x10
> > >
> > > -#define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */
> > > +#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
> > > +#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
> > >
> > > -#define MCE_CAP_DEF MCG_CTL_P
> > > +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
> > > #define MCE_BANKS_DEF 10
> > >
> >
> > It seems that current kvm doesn't support SER_P, so injecting SRAO
> > to guest will mean that guest receives VAL|UC|!PCC and RIPV event
> > from virtual processor that doesn't have SER_P.
>
> Dean also noted this. I don't think it was deliberate choice to not
> expose SER_P. Huang?
In fact, that should be a BUG. I will fix it as soon as possible.
Best Regards,
Huang Ying
^ permalink raw reply
* Re: [patch uq/master 7/8] MCE: Relay UCR MCE to guest
From: Huang Ying @ 2010-10-08 2:50 UTC (permalink / raw)
To: Marcelo Tosatti
Cc: Hidetoshi Seto, kvm@vger.kernel.org, qemu-devel@nongnu.org,
Dean Nelson
In-Reply-To: <20101006160531.GB4277@amt.cnet>
On Thu, 2010-10-07 at 00:05 +0800, Marcelo Tosatti wrote:
> On Wed, Oct 06, 2010 at 10:58:36AM +0900, Hidetoshi Seto wrote:
> > I got some more question:
> >
> > (2010/10/05 3:54), Marcelo Tosatti wrote:
> > > Index: qemu/target-i386/cpu.h
> > > ===================================================================
> > > --- qemu.orig/target-i386/cpu.h
> > > +++ qemu/target-i386/cpu.h
> > > @@ -250,16 +250,32 @@
> > > #define PG_ERROR_RSVD_MASK 0x08
> > > #define PG_ERROR_I_D_MASK 0x10
> > >
> > > -#define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */
> > > +#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
> > > +#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
> > >
> > > -#define MCE_CAP_DEF MCG_CTL_P
> > > +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
> > > #define MCE_BANKS_DEF 10
> > >
> >
> > It seems that current kvm doesn't support SER_P, so injecting SRAO
> > to guest will mean that guest receives VAL|UC|!PCC and RIPV event
> > from virtual processor that doesn't have SER_P.
>
> Dean also noted this. I don't think it was deliberate choice to not
> expose SER_P. Huang?
In fact, that should be a BUG. I will fix it as soon as possible.
Best Regards,
Huang Ying
^ permalink raw reply
* Re: [PATCH] Documentation: update-index: -z applies also to --index-info
From: Junio C Hamano @ 2010-10-08 2:49 UTC (permalink / raw)
To: Bert Wesarg; +Cc: Štěpán Němec, git
In-Reply-To: <337062f16e5b354be20b0af53a63f5c540ab0eb8.1286480355.git.bert.wesarg@googlemail.com>
Bert Wesarg <bert.wesarg@googlemail.com> writes:
> diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
> index 74d1d49..0999950 100644 Documentation/git-update-index.txt
> --- a/Documentation/git-update-index.txt
> +++ b/Documentation/git-update-index.txt
> @@ -18,9 +18,9 @@ SYNOPSIS
> [--skip-worktree | --no-skip-worktree]
> [--ignore-submodules]
> [--really-refresh] [--unresolve] [--again | -g]
> - [--info-only] [--index-info]
> - [-z] [--stdin]
> + [--info-only]
> [--verbose]
> + [[-z] --stdin | --index-info]
Hmm, this requires | to bind tighter than [] around -z, but that is a bit
counterintuitive.
Also, you can put -z much earlier, e.g. "update-index -z --add --stdin",
and your version gives a false impression that we do not allow that.
Writing it as "[-z] [--stdin | --index-info]" would be much easier to
read, even though it won't convey that -z will be no-op unless we are
reading from the standard input, either with --stdin or --index-info.
I actually think we can easily lift the "must be at the end" limitation
from both codepaths.
Move the --stdin codepath to a separate helper like read_index_info(),
remove the limitation, and add a new limitation that --stdin/--index-info
can be given only once (as the reader will read thru EOF and the second
call to the reader won't help us). And do the reading after processing
all the command line stuff (i.e. move read_index_info() call after the
option parsing loop), to allow "update-index --stdin --add hello.c" to add
new paths read from standard input and also hello.c was given from the
command line.
Wouldn't it make much more sense to spend brain cycles to write and review
such a patch, rather than documenting an unnecessary limitation?
Hmm?
^ permalink raw reply
* Re: 2.6.35-rc1 regression with pvclock and smp guests
From: Zachary Amsden @ 2010-10-08 2:47 UTC (permalink / raw)
To: Arjan Koers
Cc: kvm, Marcelo Tosatti, Michael Tokarev, Avi Kivity, Glauber Costa,
Andre Przywara
In-Reply-To: <4CAE6203.6040902@xutrox.com>
On 10/07/2010 02:12 PM, Arjan Koers wrote:
> On 2010-10-03 01:42, Zachary Amsden wrote:
> ...
>
>> Umm... do you guys have this commit? This is supposed to address the
>> issue where the guest keeps resetting the TSC. A guest which does that
>> will break kvmclock. It only happens on SMP, and it's much worse on AMD
>> CPUs...
>>
>> sound like your scenario.
>>
>> commit bd59fc8ff95126f27b7a0df1b6cc602aa428812d
>> Author: Zachary Amsden<zamsden@redhat.com>
>> Date: Thu Aug 19 22:07:26 2010 -1000
>>
>
> This commit fixes the problem:
>
> commit aad07c4f92bae2edaa42bcef84c2afdd0d082458
> Author: Zachary Amsden<zamsden@redhat.com>
> Date: Thu Aug 19 22:07:19 2010 -1000
>
> KVM: x86: Move TSC reset out of vmcb_init
>
> The VMCB is reset whenever we receive a startup IPI, so Linux is setting
> TSC back to zero happens very late in the boot process and destabilizing
> the TSC. Instead, just set TSC to zero once at VCPU creation time.
>
> Why the separate patch? So git-bisect is your friend.
>
Okay, apparently I need to go poke around 2.6.35 and see what patches
made it there and what patches didn't.
^ permalink raw reply
* RE: [PATCH v3 5/7] mtd: m25p80: add support to parse the SPI flash's partitions
From: Hu Mingkai-B21284 @ 2010-10-08 2:42 UTC (permalink / raw)
To: Grant Likely
Cc: linuxppc-dev, Gala Kumar-B11780, linux-mtd, Zang Roy-R61911,
spi-devel-general
In-Reply-To: <AANLkTi=eBA+i7kCOrEPao1AXofKUjBQokWLXFpgx3WND@mail.gmail.com>
> -----Original Message-----
> From: glikely@secretlab.ca [mailto:glikely@secretlab.ca] On Behalf Of =
Grant
> Likely
> Sent: Friday, October 01, 2010 5:35 AM
> To: Hu Mingkai-B21284
> Cc: linuxppc-dev@ozlabs.org; spi-devel-general@lists.sourceforge.net; =
linux-
> mtd@lists.infradead.org; Gala Kumar-B11780; Zang Roy-R61911
> Subject: Re: [PATCH v3 5/7] mtd: m25p80: add support to parse the SPI =
flash's
> partitions
>=20
> On Thu, Sep 30, 2010 at 5:00 PM, Mingkai Hu <Mingkai.hu@freescale.com> =
wrote:
> > Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> > ---
> > v3:
> > =A0- Move the SPI flash partition code to the probe function.
> >
> > =A0drivers/mtd/devices/m25p80.c | =A0 39 =
+++++++++++++++++++++++++++------------
> > =A01 files changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/mtd/devices/m25p80.c =
b/drivers/mtd/devices/m25p80.c
> > index 6f512b5..47d53c7 100644
> > --- a/drivers/mtd/devices/m25p80.c
> > +++ b/drivers/mtd/devices/m25p80.c
> > @@ -772,7 +772,7 @@ static const struct spi_device_id *__devinit
> jedec_probe(struct spi_device *spi)
> > =A0static int __devinit m25p_probe(struct spi_device *spi)
> > =A0{
> > =A0 =A0 =A0 =A0const struct spi_device_id =A0 =A0 =A0*id =3D =
spi_get_device_id(spi);
> > - =A0 =A0 =A0 struct flash_platform_data =A0 =A0 =A0*data;
> > + =A0 =A0 =A0 struct flash_platform_data =A0 =A0 =A0data, *pdata;
> > =A0 =A0 =A0 =A0struct m25p =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
*flash;
> > =A0 =A0 =A0 =A0struct flash_info =A0 =A0 =A0 =A0 =A0 =A0 =A0 *info;
> > =A0 =A0 =A0 =A0unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0i;
> > @@ -782,13 +782,27 @@ static int __devinit m25p_probe(struct =
spi_device *spi)
> > =A0 =A0 =A0 =A0 * a chip ID, try the JEDEC id commands; they'll work =
for most
> > =A0 =A0 =A0 =A0 * newer chips, even if we don't recognize the =
particular chip.
> > =A0 =A0 =A0 =A0 */
> > - =A0 =A0 =A0 data =3D spi->dev.platform_data;
> > - =A0 =A0 =A0 if (data && data->type) {
> > + =A0 =A0 =A0 pdata =3D spi->dev.platform_data;
> > + =A0 =A0 =A0 if (!pdata && spi->dev.of_node) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 int nr_parts;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct mtd_partition *parts;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct device_node *np =3D =
spi->dev.of_node;
> > +
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 nr_parts =3D =
of_mtd_parse_partitions(&spi->dev, np, &parts);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (nr_parts) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata =3D &data;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(pdata, 0, =
sizeof(*pdata));
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->parts =3D =
parts;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->nr_parts =3D =
nr_parts;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> > + =A0 =A0 =A0 }
>=20
> Yes, this is the correct way to go about adding the partitions.
> However, this patch can be made simpler by not renaming 'data' to
> 'pdata' and by moving the above code down to just before the partition
> information is actually used. in the OF case, only the parts and the
> nr_parts values written into data, and those values aren't used until
> the last part of the probe function.
>=20
> Regardless, in principle this patch is correct:
>=20
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
>=20
> > +
> > + =A0 =A0 =A0 if (pdata && pdata->type) {
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const struct spi_device_id *plat_id;
> >
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (i =3D 0; i < =
ARRAY_SIZE(m25p_ids) - 1; i++) {
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0plat_id =3D =
&m25p_ids[i];
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (strcmp(data->type, =
plat_id->name))
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if =
(strcmp(pdata->type, plat_id->name))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0continue;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> > @@ -796,7 +810,8 @@ static int __devinit m25p_probe(struct =
spi_device *spi)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (i < ARRAY_SIZE(m25p_ids) - 1)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0id =3D plat_id;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(&spi->dev, =
"unrecognized id %s\n", data-
> >type);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(&spi->dev, =
"unrecognized id %s\n",
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 pdata->type);
> > =A0 =A0 =A0 =A0}
> >
> > =A0 =A0 =A0 =A0info =3D (void *)id->driver_data;
> > @@ -847,8 +862,8 @@ static int __devinit m25p_probe(struct =
spi_device *spi)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0write_sr(flash, 0);
> > =A0 =A0 =A0 =A0}
> >
> > - =A0 =A0 =A0 if (data && data->name)
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 flash->mtd.name =3D data->name;
> > + =A0 =A0 =A0 if (pdata && pdata->name)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 flash->mtd.name =3D pdata->name;
> > =A0 =A0 =A0 =A0else
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0flash->mtd.name =3D =
dev_name(&spi->dev);
> >
> > @@ -919,9 +934,9 @@ static int __devinit m25p_probe(struct =
spi_device *spi)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0part_probes, &parts, 0);
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> >
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (nr_parts <=3D 0 && data && =
data->parts) {
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 parts =3D data->parts;
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 nr_parts =3D =
data->nr_parts;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (nr_parts <=3D 0 && pdata && =
pdata->parts) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 parts =3D =
pdata->parts;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 nr_parts =3D =
pdata->nr_parts;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>=20
> As per my comment earlier; since parts and nr_parts isn't needed
> before this point, this block could simply be:
>=20
> if (nr_parts <=3D 0 && data && data->parts) {
> parts =3D data->parts;
> nr_parts =3D data->nr_parts;
> }
> if (nr_parts <=3D 0 && spi->dev.of_node)
> =A0 =A0 =A0 nr_parts =3D of_mtd_parse_partitions(&spi->dev, np, =
&parts);
>=20
> And most of the other changes to this file goes away. Simpler, yes?
>=20
Yes, you're right, I'll fix it. Also thanks for your suggestion and ACK.
Thanks,
Mingkai
^ permalink raw reply
* RE: [PATCH v3 5/7] mtd: m25p80: add support to parse the SPI flash's partitions
From: Hu Mingkai-B21284 @ 2010-10-08 2:42 UTC (permalink / raw)
To: Grant Likely
Cc: linuxppc-dev, Gala Kumar-B11780, linux-mtd, Zang Roy-R61911,
spi-devel-general
In-Reply-To: <AANLkTi=eBA+i7kCOrEPao1AXofKUjBQokWLXFpgx3WND@mail.gmail.com>
> -----Original Message-----
> From: glikely@secretlab.ca [mailto:glikely@secretlab.ca] On Behalf Of Grant
> Likely
> Sent: Friday, October 01, 2010 5:35 AM
> To: Hu Mingkai-B21284
> Cc: linuxppc-dev@ozlabs.org; spi-devel-general@lists.sourceforge.net; linux-
> mtd@lists.infradead.org; Gala Kumar-B11780; Zang Roy-R61911
> Subject: Re: [PATCH v3 5/7] mtd: m25p80: add support to parse the SPI flash's
> partitions
>
> On Thu, Sep 30, 2010 at 5:00 PM, Mingkai Hu <Mingkai.hu@freescale.com> wrote:
> > Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> > ---
> > v3:
> > - Move the SPI flash partition code to the probe function.
> >
> > drivers/mtd/devices/m25p80.c | 39 +++++++++++++++++++++++++++------------
> > 1 files changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> > index 6f512b5..47d53c7 100644
> > --- a/drivers/mtd/devices/m25p80.c
> > +++ b/drivers/mtd/devices/m25p80.c
> > @@ -772,7 +772,7 @@ static const struct spi_device_id *__devinit
> jedec_probe(struct spi_device *spi)
> > static int __devinit m25p_probe(struct spi_device *spi)
> > {
> > const struct spi_device_id *id = spi_get_device_id(spi);
> > - struct flash_platform_data *data;
> > + struct flash_platform_data data, *pdata;
> > struct m25p *flash;
> > struct flash_info *info;
> > unsigned i;
> > @@ -782,13 +782,27 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > * a chip ID, try the JEDEC id commands; they'll work for most
> > * newer chips, even if we don't recognize the particular chip.
> > */
> > - data = spi->dev.platform_data;
> > - if (data && data->type) {
> > + pdata = spi->dev.platform_data;
> > + if (!pdata && spi->dev.of_node) {
> > + int nr_parts;
> > + struct mtd_partition *parts;
> > + struct device_node *np = spi->dev.of_node;
> > +
> > + nr_parts = of_mtd_parse_partitions(&spi->dev, np, &parts);
> > + if (nr_parts) {
> > + pdata = &data;
> > + memset(pdata, 0, sizeof(*pdata));
> > + pdata->parts = parts;
> > + pdata->nr_parts = nr_parts;
> > + }
> > + }
>
> Yes, this is the correct way to go about adding the partitions.
> However, this patch can be made simpler by not renaming 'data' to
> 'pdata' and by moving the above code down to just before the partition
> information is actually used. in the OF case, only the parts and the
> nr_parts values written into data, and those values aren't used until
> the last part of the probe function.
>
> Regardless, in principle this patch is correct:
>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
>
> > +
> > + if (pdata && pdata->type) {
> > const struct spi_device_id *plat_id;
> >
> > for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
> > plat_id = &m25p_ids[i];
> > - if (strcmp(data->type, plat_id->name))
> > + if (strcmp(pdata->type, plat_id->name))
> > continue;
> > break;
> > }
> > @@ -796,7 +810,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > if (i < ARRAY_SIZE(m25p_ids) - 1)
> > id = plat_id;
> > else
> > - dev_warn(&spi->dev, "unrecognized id %s\n", data-
> >type);
> > + dev_warn(&spi->dev, "unrecognized id %s\n",
> > + pdata->type);
> > }
> >
> > info = (void *)id->driver_data;
> > @@ -847,8 +862,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > write_sr(flash, 0);
> > }
> >
> > - if (data && data->name)
> > - flash->mtd.name = data->name;
> > + if (pdata && pdata->name)
> > + flash->mtd.name = pdata->name;
> > else
> > flash->mtd.name = dev_name(&spi->dev);
> >
> > @@ -919,9 +934,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > part_probes, &parts, 0);
> > }
> >
> > - if (nr_parts <= 0 && data && data->parts) {
> > - parts = data->parts;
> > - nr_parts = data->nr_parts;
> > + if (nr_parts <= 0 && pdata && pdata->parts) {
> > + parts = pdata->parts;
> > + nr_parts = pdata->nr_parts;
> > }
>
> As per my comment earlier; since parts and nr_parts isn't needed
> before this point, this block could simply be:
>
> if (nr_parts <= 0 && data && data->parts) {
> parts = data->parts;
> nr_parts = data->nr_parts;
> }
> if (nr_parts <= 0 && spi->dev.of_node)
> nr_parts = of_mtd_parse_partitions(&spi->dev, np, &parts);
>
> And most of the other changes to this file goes away. Simpler, yes?
>
Yes, you're right, I'll fix it. Also thanks for your suggestion and ACK.
Thanks,
Mingkai
^ permalink raw reply
* Re: [PATCH 06/15] qla4xxx: Do not wait for the outstanding commands to complete
From: Mike Christie @ 2010-10-08 2:46 UTC (permalink / raw)
To: Vikas Chaudhary
Cc: James.Bottomley@suse.de, linux-scsi@vger.kernel.org,
Nilesh Javali, Ravi Anand
In-Reply-To: <5E4F49720D0BAD499EE1F01232234BA87129406789@AVEXMB1.qlogic.org>
[-- Attachment #1: Type: text/plain, Size: 2380 bytes --]
On 10/07/2010 12:49 AM, Vikas Chaudhary wrote:
> From: Nilesh Javali<nilesh.javali@qlogic.com>
>
> Do not wait for the outstanding commands to complete in case
> of firmware hang.
>
> Signed-off-by: Nilesh Javali<nilesh.javali@qlogic.com>
> Signed-off-by: Vikas Chaudhary<vikas.chaudhary@qlogic.com>
> Signed-off-by: Ravi Anand<ravi.anand@qlogic.com>
> ---
> drivers/scsi/qla4xxx/ql4_os.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
> index 56962e5..a6455fb 100644
> --- a/drivers/scsi/qla4xxx/ql4_os.c
> +++ b/drivers/scsi/qla4xxx/ql4_os.c
> @@ -1102,7 +1102,8 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
> ha->host_no, __func__));
> status = ha->isp_ops->reset_firmware(ha);
> if (status == QLA_SUCCESS) {
> - qla4xxx_cmd_wait(ha);
> + if (!test_bit(AF_FW_RECOVERY,&ha->flags))
> + qla4xxx_cmd_wait(ha);
> ha->isp_ops->disable_intrs(ha);
> qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
> qla4xxx_abort_active_cmds(ha, DID_RESET<< 16);
> @@ -1119,7 +1120,8 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
> * or if stop_firmware fails for ISP-82xx.
> * This is the default case for ISP-4xxx */
> if (!is_qla8022(ha) || reset_chip) {
> - qla4xxx_cmd_wait(ha);
> + if (!test_bit(AF_FW_RECOVERY,&ha->flags))
> + qla4xxx_cmd_wait(ha);
> qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
> qla4xxx_abort_active_cmds(ha, DID_RESET<< 16);
> DEBUG2(ql4_printk(KERN_INFO, ha,
If we go from qla4xxx_eh_host_reset->qla4xxx_recover_adapter and you do
not wait, is is possible for the driver to be accessing scsi commands
after qla4xxx_eh_host_reset returns? If so I think there is a problem
where the scsi eh will fail or retry the cmd so the memory for the scsi
command could be reallocated/freed.
On a related note, has qla4xxx_eh_host_reset ever returned SUCCESS? I
think there is a problem in qla4xxx_cmd_wait when the scsi eh is
running. At that time blk_finish_request->blk_queue_end_tag is not going
to be run, because if the driver were to call scsi_done the block layer
would do blk_complete_request and the blk_mark_rq_complete would fail
(this is because the scsi/block eh timeout could has already marked it
complete).
I think you need the attached patch.
[-- Attachment #2: qla4xxx-fix-cmd-wait-cmd-check.patch --]
[-- Type: text/plain, Size: 1260 bytes --]
qla4xxx: Fix cmd check in qla4xxx_cmd_wait
If the command has timedout then the block layer has called
blk_mark_rq_complete. If qla4xxx_cmd_wait is then called
from qla4xxx_eh_host_reset, we will always fail, because if
the driver calls scsi_done then the the block layer will fail
at blk_complete_request's blk_mark_rq_complete call instead of
calling the normal completion path including the function,
blk_queue_end_tag, which releases the tag.
Patch is not tested.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 370d40f..97f6d68 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -885,7 +885,13 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
/* Find a command that hasn't completed. */
for (index = 0; index < ha->host->can_queue; index++) {
cmd = scsi_host_find_tag(ha->host, index);
- if (cmd != NULL)
+ /*
+ * We cannot just check if the index is valid,
+ * becase if we are run from the scsi eh, then
+ * the scsi/block layer is going to prevent
+ * the tag from being released.
+ */
+ if (cmd != NULL && CMD_SP(cmd))
break;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
^ permalink raw reply related
* [PATCH] drm/radeon/kms: make TV/DFP table info less verbose
From: Alex Deucher @ 2010-10-08 2:38 UTC (permalink / raw)
To: airlied, dri-devel
Make TV standard and DFP table revisions debug only.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
---
drivers/gpu/drm/radeon/radeon_atombios.c | 18 +++++++++---------
drivers/gpu/drm/radeon/radeon_combios.c | 26 +++++++++++++-------------
2 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 2b44cbc..04cac7e 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1613,39 +1613,39 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
switch (tv_info->ucTV_BootUpDefaultStandard) {
case ATOM_TV_NTSC:
tv_std = TV_STD_NTSC;
- DRM_INFO("Default TV standard: NTSC\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC\n");
break;
case ATOM_TV_NTSCJ:
tv_std = TV_STD_NTSC_J;
- DRM_INFO("Default TV standard: NTSC-J\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
break;
case ATOM_TV_PAL:
tv_std = TV_STD_PAL;
- DRM_INFO("Default TV standard: PAL\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL\n");
break;
case ATOM_TV_PALM:
tv_std = TV_STD_PAL_M;
- DRM_INFO("Default TV standard: PAL-M\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
break;
case ATOM_TV_PALN:
tv_std = TV_STD_PAL_N;
- DRM_INFO("Default TV standard: PAL-N\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
break;
case ATOM_TV_PALCN:
tv_std = TV_STD_PAL_CN;
- DRM_INFO("Default TV standard: PAL-CN\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
break;
case ATOM_TV_PAL60:
tv_std = TV_STD_PAL_60;
- DRM_INFO("Default TV standard: PAL-60\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
break;
case ATOM_TV_SECAM:
tv_std = TV_STD_SECAM;
- DRM_INFO("Default TV standard: SECAM\n");
+ DRM_DEBUG_KMS("Default TV standard: SECAM\n");
break;
default:
tv_std = TV_STD_NTSC;
- DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+ DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
break;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index a04b7a6..7b7ea26 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -913,47 +913,47 @@ radeon_combios_get_tv_info(struct radeon_device *rdev)
switch (RBIOS8(tv_info + 7) & 0xf) {
case 1:
tv_std = TV_STD_NTSC;
- DRM_INFO("Default TV standard: NTSC\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC\n");
break;
case 2:
tv_std = TV_STD_PAL;
- DRM_INFO("Default TV standard: PAL\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL\n");
break;
case 3:
tv_std = TV_STD_PAL_M;
- DRM_INFO("Default TV standard: PAL-M\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
break;
case 4:
tv_std = TV_STD_PAL_60;
- DRM_INFO("Default TV standard: PAL-60\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
break;
case 5:
tv_std = TV_STD_NTSC_J;
- DRM_INFO("Default TV standard: NTSC-J\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
break;
case 6:
tv_std = TV_STD_SCART_PAL;
- DRM_INFO("Default TV standard: SCART-PAL\n");
+ DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n");
break;
default:
tv_std = TV_STD_NTSC;
- DRM_INFO
+ DRM_DEBUG_KMS
("Unknown TV standard; defaulting to NTSC\n");
break;
}
switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) {
case 0:
- DRM_INFO("29.498928713 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n");
break;
case 1:
- DRM_INFO("28.636360000 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n");
break;
case 2:
- DRM_INFO("14.318180000 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n");
break;
case 3:
- DRM_INFO("27.000000000 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n");
break;
default:
break;
@@ -1324,7 +1324,7 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
if (tmds_info) {
ver = RBIOS8(tmds_info);
- DRM_INFO("DFP table revision: %d\n", ver);
+ DRM_DEBUG_KMS("DFP table revision: %d\n", ver);
if (ver == 3) {
n = RBIOS8(tmds_info + 5) + 1;
if (n > 4)
@@ -1408,7 +1408,7 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
if (offset) {
ver = RBIOS8(offset);
- DRM_INFO("External TMDS Table revision: %d\n", ver);
+ DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver);
tmds->slave_addr = RBIOS8(offset + 4 + 2);
tmds->slave_addr >>= 1; /* 7 bit addressing */
gpio = RBIOS8(offset + 4 + 3);
--
1.7.1.1
^ permalink raw reply related
* [PATCH] Fix a complex race in hrtimer code.
From: Salman Qazi @ 2010-10-08 2:33 UTC (permalink / raw)
To: akpm, linux-kernel
The race is described as follows:
CPU X CPU Y
remove_hrtimer
// state & QUEUED == 0
timer->state = CALLBACK
unlock timer base
timer->f(n) //very long
hrtimer_start
lock timer base
remove_hrtimer // no effect
hrtimer_enqueue
timer->state = CALLBACK |
QUEUED
unlock timer base
hrtimer_start
lock timer base
remove_hrtimer
mode = INACTIVE
// CALLBACK bit lost!
switch_hrtimer_base
CALLBACK bit not set:
timer->base
changes to a
different CPU.
lock this CPU's timer base
Bug reproducible and fix testable using a kernel module that hrtimer_start()s
a timer with a very long running callback from multiple CPUs:
MODULE_LICENSE("GPL");
static long timer_func_time = 1000;
module_param(timer_func_time, long, 0600);
static long timer_starts = 2500;
module_param(timer_starts, long, 0600);
static long timer_expire = 1000;
module_param(timer_expire, long, 0600);
DEFINE_PER_CPU(struct task_struct *, hrtimer_thread);
/* There are other issues, like deadlocks between multiple hrtimer_start observed
* calls, at least in 2.6.34 that this lock works around. Will look into
* those later.
*/
static DEFINE_SPINLOCK(blah_lock);
static ktime_t mytime;
static struct hrtimer timer;
static enum hrtimer_restart timer_restart(struct hrtimer *timer)
{
unsigned long i;
/* We have to make the callback longer to improve the
* probability of having a race.
*/
for (i = 0; i < timer_func_time / 100; i++) {
touch_nmi_watchdog();
touch_softlockup_watchdog();
udelay(100);
}
return HRTIMER_NORESTART;
}
static int restart_hrtimer_repeatedly(void *input)
{
int i;
unsigned long range;
while (!kthread_should_stop()) {
for (i = 0; i < timer_starts; i++) {
/* Avoid deadlocks for now */
spin_lock(&blah_lock);
hrtimer_start(&timer, mytime, HRTIMER_MODE_REL);
spin_unlock(&blah_lock);
touch_nmi_watchdog();
touch_softlockup_watchdog();
}
cond_resched();
}
hrtimer_cancel(&timer);
return 0;
}
static int hrtimer_unit_test_init(void)
{
int cpu;
mytime = ktime_set(0, 0);
mytime = ktime_add_ns(mytime, timer_expire);
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = timer_restart;
for_each_online_cpu(cpu) {
per_cpu(hrtimer_thread, cpu) = kthread_create(
restart_hrtimer_repeatedly, NULL, "hrtimer_test/%d",
cpu);
if (IS_ERR(per_cpu(hrtimer_thread, cpu))) {
printk(KERN_ERR
"Failed to create hrtimer test thread\n");
BUG();
}
kthread_bind(per_cpu(hrtimer_thread, cpu), cpu);
wake_up_process(per_cpu(hrtimer_thread, cpu));
}
return 0;
}
static void hrtimer_unit_test_exit(void)
{
int cpu;
for_each_online_cpu(cpu) {
(void)kthread_stop(per_cpu(hrtimer_thread, cpu));
}
}
module_init(hrtimer_unit_test_init);
module_exit(hrtimer_unit_test_exit);
---
kernel/hrtimer.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 1decafb..4769c51 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -944,8 +944,8 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
debug_deactivate(timer);
timer_stats_hrtimer_clear_start_info(timer);
reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
- __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
- reprogram);
+ __remove_hrtimer(timer, base,
+ (timer->state & HRTIMER_STATE_CALLBACK), reprogram);
return 1;
}
return 0;
@@ -1231,6 +1231,9 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
enqueue_hrtimer(timer, base);
}
+
+ BUG_ON(!(timer->state & HRTIMER_STATE_CALLBACK));
+
timer->state &= ~HRTIMER_STATE_CALLBACK;
}
^ permalink raw reply related
* RE: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by page
From: Hu Mingkai-B21284 @ 2010-10-08 2:15 UTC (permalink / raw)
To: Anton Vorontsov, Grant Likely
Cc: David Brownell, linuxppc-dev, Gala Kumar-B11780, linux-mtd,
spi-devel-general
In-Reply-To: <20100930150633.GA13741@oksana.dev.rtsoft.ru>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIFNlcHRl
bWJlciAzMCwgMjAxMCAxMTowNyBQTQ0KPiBUbzogR3JhbnQgTGlrZWx5DQo+IENjOiBEYXZpZCBC
cm93bmVsbDsgbGludXhwcGMtZGV2QG96bGFicy5vcmc7IEh1IE1pbmdrYWktQjIxMjg0OyBsaW51
eC0NCj4gbXRkQGxpc3RzLmluZnJhZGVhZC5vcmc7IEdhbGEgS3VtYXItQjExNzgwOyBzcGktZGV2
ZWwtDQo+IGdlbmVyYWxAbGlzdHMuc291cmNlZm9yZ2UubmV0DQo+IFN1YmplY3Q6IFJlOiBbUEFU
Q0ggdjMgNi83XSBtdGQ6IG0yNXA4MDogYWRkIGEgcmVhZCBmdW5jdGlvbiB0byByZWFkIHBhZ2Ug
YnkNCj4gcGFnZQ0KPiANCj4gT24gVGh1LCBTZXAgMzAsIDIwMTAgYXQgMTE6NDE6NDBQTSArMDkw
MCwgR3JhbnQgTGlrZWx5IHdyb3RlOg0KPiA+IE9uIFRodSwgU2VwIDMwLCAyMDEwIGF0IDExOjE2
IFBNLCBHcmFudCBMaWtlbHkNCj4gPiA8Z3JhbnQubGlrZWx5QHNlY3JldGxhYi5jYT4gd3JvdGU6
DQo+ID4gPiBPbiBUaHUsIFNlcCAzMCwgMjAxMCBhdCA3OjQ2IFBNLCBEYXZpZCBCcm93bmVsbCA8
ZGF2aWQtYkBwYWNiZWxsLm5ldD4gd3JvdGU6DQo+ID4gPj4NCj4gPiA+PiAtLS0gT24gVGh1LCA5
LzMwLzEwLCBNaW5na2FpIEh1IDxNaW5na2FpLmh1QGZyZWVzY2FsZS5jb20+IHdyb3RlOg0KPiA+
ID4+DQo+ID4gPj4+IEZyb206IE1pbmdrYWkgSHUgPE1pbmdrYWkuaHVAZnJlZXNjYWxlLmNvbT4N
Cj4gPiA+Pj4gU3ViamVjdDogW1BBVENIIHYzIDYvN10gbXRkOiBtMjVwODA6IGFkZCBhIHJlYWQg
ZnVuY3Rpb24gdG8gcmVhZA0KPiA+ID4+PiBwYWdlIGJ5IHBhZ2UNCj4gPiA+Pg0KPiA+ID4+IE5B
Sy4NCj4gPiA+Pg0KPiA+ID4+IFdlIHdlbnQgb3ZlciB0aGlzIGJlZm9yZS4NCj4gPiA+DQo+ID4g
PiBZZXMsIEkgYWdyZWUgd2l0aCBEYXZpZCBvbiB0aGlzLiDCoElmIGxhcmdlIHRyYW5zZmVycyBk
b24ndCB3b3JrLA0KPiA+ID4gdGhlbiBpdCBpcyB0aGUgU1BJIG1hc3RlciBkcml2ZXIgdGhhdCBp
cyBidWdneS4NCj4gPg0KPiA+IEJ5IHRoZSB3YXksIGRvZXMgdGhpcyBmaXggeW91ciBwcm9ibGVt
Pw0KPiA+DQo+ID4gaHR0cHM6Ly9wYXRjaHdvcmsua2VybmVsLm9yZy9wYXRjaC8xODQ3NTIvDQo+
IA0KPiBJdCBzaG91bGRuJ3QuIEFGQUlLLCBlU1BJIGlzIFBJTy1vbmx5IGNvbnRyb2xsZXIsIGFu
ZCB0aGUgb3ZlcnJ1biBmaXggaXMgZm9yIHRoZQ0KPiBETUEgbW9kZS4NCj4gDQo+IFRoYW5rcywN
Cj4gDQo+IHAucy4gQnR3LCBpbiBwYXRjaCAzLzcsIGlzX2RtYV9tYXBwZWQgYXJndW1lbnQgb2Yg
ZnNsX2VzcGlfYnVmcygpIGlzIHVubmVlZGVkLg0KPiANCg0KWWVzLCB0aGUgaXNfZG1hX21hcHBl
ZCBpc24ndCBuZWVkZWQsIEknbGwgcmVtb3ZlIGl0Lg0KDQpUaGFua3MsDQpNaW5na2FpDQo=
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.