All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCHv5 1/8] commit.c: prefer get_header() to manual searching
From: Sverre Rabbelier @ 2010-10-07 21:12 UTC (permalink / raw)
  To: Pat Notz; +Cc: git
In-Reply-To: <AANLkTinj5eZ7p8qW7U1iqNcjN4EG6HcftD2+etGvSKPA@mail.gmail.com>

Heya,

On Thu, Oct 7, 2010 at 23:11, Sverre Rabbelier <srabbelier@gmail.com> wrote:
> Cover letter?

Ah, there it is, sorry for the noise.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH] PM: add synchronous runtime interface for interrupt handlers
From: Rafael J. Wysocki @ 2010-10-07 21:11 UTC (permalink / raw)
  To: Alan Stern, Kevin Hilman; +Cc: Linux-pm mailing list, Partha Basak, linux-omap
In-Reply-To: <Pine.LNX.4.44L0.1010071318570.1753-100000@iolanthe.rowland.org>

On Thursday, October 07, 2010, Alan Stern wrote:
> On Thu, 7 Oct 2010, Kevin Hilman wrote:
> 
> > My confusion is not about the use of spinlocks, it's a question of what
> > is being busy-waited for, and the thread that is being waited for is
> > going to complete when interrupts are disabled.
> > 
> > Sorry to be dense, but can you (re)summarize what you're proposing as I
> > think I'm getting mixed up with all the various options we've been
> > tossing around.
> > 
> > If it can work, I'm certainly in favor of a busy-wait approach as it 
> > really ensures that sync requests are handled quickly.
> 
> Okay, here's the story in a nutshell.  Allowing a subsystem's or
> driver's runtime-PM callbacks to run with interrupts disabled faces two
> obstacles:
> 
>    (1): We don't want two different CPUs to run callbacks for the
> 	same device at the same time.  So if a callback is already
> 	running on one CPU (i.e., if the device's runtime status is
> 	either SUSPENDING or RESUMING) then another CPU can't be
> 	allowed to invoke a callback.
> 
> 	Thus, you can't do a synchronous pm_runtime_resume_irq()
> 	if the device is in the middle of a suspend or resume
> 	operation.  We're left with two choices: Fail the synchronous
> 	call and force the driver to defer matters to a workqueue
> 	(possibly masking an IRQ line in the meantime), or busy-wait
> 	until the concurrent operation finishes.
> 
> 	If the PM core simply avoids releasing dev->power.lock before
> 	invoking the runtime_suspend or runtime_resume callback, the
> 	end result is almost the same as with busy-waiting.

This is slightly more complicated, because suspend is a bit different from
resume.  I think it's generally acceptable to refuse to do a "fast path" suspend
if the device state is not RPM_ACTIVE at the moment, but refusing to do
a "fast path" resume may be more problematic (more on that later).

>    (2): In general we can't resume a device if its parent is suspended.
> 	If the parent's runtime_resume routine needs to run with
> 	interrupts enabled then there's no way to resume the device
> 	while keeping interrupts disabled.
> 
> 	Possible solutions involve, again, deferring matters to a
> 	workqueue, or else simply not allowing the situation to arise
> 	in the first place (forbid a device to have interrupt-disabled 
> 	callbacks unless its parent does too or the parent doesn't use 
> 	runtime PM at all).
> 
> In general I'm against the solutions that require a workqueue.

OK

> Raphael appears to favor workqueues for (1) and be against them for (2).

The particular case we need to handle (I think) is that some devices need to be
resumed "atomically" as a part of bringing a CPU package out of a C-like-state
(Kevin, is that correct?).  In that case not only we can't defer the resume (by
using a workqueue), but also we have to finish the resume within strict time
constraints (the time to leave the given C-like-state is one of the parameters
used by cpuidle governors to decide which state to choose).

On the other hand, busy waiting (by looping) in the case the state is
RPM_RESUMING is as though the callbacks were executed under a spinlock and we
happened to wait on it.  I'd prefer to avoid that.  Moreover, if the state is
RPM_SUSPENDING at the time a "fast path" resume is started, we are almost
guaranteed to violate the time constraints (by busy waiting for the suspend to
complete and carrying out the resume).

So, here's an idea:

First, let's introduce two flags in struct dev_pm_info, irq_safe and
fast_resume.  The former has to be set so that the things above work.

Second, let's add a new flag to pass to __pm_runtime_{suspend|resume}(),
RPM_FAST_RESUME such that if it is passed to __pm_runtime_suspend(), it
causes fast_resume to be set for the given device (if the status is already
RPM_SUSPENDED, it just sets the flag, otherwise it suspends the device
normally and then sets the flag).  Now, if fast_resume is set,
__pm_runtime_resume() has to be passed RPM_FAST_RESUME, or it will
fail (it also will fail if passed RPM_FAST_RESUME and fast_resume isn't
set).  In that case the status has to be RPM_SUSPENDED or RPM_RESUMING
(otherwise fast_resume won't be set) and if it is RPM_RESUMING, this means
that the other resume has been called with RPM_FAST_RESUME too (it would
fail otherwise), so it's fine to busy loop until the status is RPM_SUSPENDED
(it's the caller's problem to avoid that).  RPM_FAST_RESUME causes
__pm_runtime_resume() to avod turning interrupts on.

If necessary, there may be a flag for __pm_runtime_suspend() that will
carry out "atomic" suspend, but I'm not sure if that's necessary.  Kevin?

Rafael

^ permalink raw reply

* Re: [PATCHv5 1/8] commit.c: prefer get_header() to manual searching
From: Sverre Rabbelier @ 2010-10-07 21:11 UTC (permalink / raw)
  To: Pat Notz; +Cc: git
In-Reply-To: <1286478657-61581-2-git-send-email-patnotz@gmail.com>

Heya,

On Thu, Oct 7, 2010 at 21:10, Pat Notz <patnotz@gmail.com> wrote:
> Signed-off-by: Pat Notz <patnotz@gmail.com>

Cover letter?

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH] PM: add synchronous runtime interface for interrupt handlers
From: Rafael J. Wysocki @ 2010-10-07 21:11 UTC (permalink / raw)
  To: Alan Stern, Kevin Hilman; +Cc: Partha Basak, Linux-pm mailing list, linux-omap
In-Reply-To: <Pine.LNX.4.44L0.1010071318570.1753-100000@iolanthe.rowland.org>

On Thursday, October 07, 2010, Alan Stern wrote:
> On Thu, 7 Oct 2010, Kevin Hilman wrote:
> 
> > My confusion is not about the use of spinlocks, it's a question of what
> > is being busy-waited for, and the thread that is being waited for is
> > going to complete when interrupts are disabled.
> > 
> > Sorry to be dense, but can you (re)summarize what you're proposing as I
> > think I'm getting mixed up with all the various options we've been
> > tossing around.
> > 
> > If it can work, I'm certainly in favor of a busy-wait approach as it 
> > really ensures that sync requests are handled quickly.
> 
> Okay, here's the story in a nutshell.  Allowing a subsystem's or
> driver's runtime-PM callbacks to run with interrupts disabled faces two
> obstacles:
> 
>    (1): We don't want two different CPUs to run callbacks for the
> 	same device at the same time.  So if a callback is already
> 	running on one CPU (i.e., if the device's runtime status is
> 	either SUSPENDING or RESUMING) then another CPU can't be
> 	allowed to invoke a callback.
> 
> 	Thus, you can't do a synchronous pm_runtime_resume_irq()
> 	if the device is in the middle of a suspend or resume
> 	operation.  We're left with two choices: Fail the synchronous
> 	call and force the driver to defer matters to a workqueue
> 	(possibly masking an IRQ line in the meantime), or busy-wait
> 	until the concurrent operation finishes.
> 
> 	If the PM core simply avoids releasing dev->power.lock before
> 	invoking the runtime_suspend or runtime_resume callback, the
> 	end result is almost the same as with busy-waiting.

This is slightly more complicated, because suspend is a bit different from
resume.  I think it's generally acceptable to refuse to do a "fast path" suspend
if the device state is not RPM_ACTIVE at the moment, but refusing to do
a "fast path" resume may be more problematic (more on that later).

>    (2): In general we can't resume a device if its parent is suspended.
> 	If the parent's runtime_resume routine needs to run with
> 	interrupts enabled then there's no way to resume the device
> 	while keeping interrupts disabled.
> 
> 	Possible solutions involve, again, deferring matters to a
> 	workqueue, or else simply not allowing the situation to arise
> 	in the first place (forbid a device to have interrupt-disabled 
> 	callbacks unless its parent does too or the parent doesn't use 
> 	runtime PM at all).
> 
> In general I'm against the solutions that require a workqueue.

OK

> Raphael appears to favor workqueues for (1) and be against them for (2).

The particular case we need to handle (I think) is that some devices need to be
resumed "atomically" as a part of bringing a CPU package out of a C-like-state
(Kevin, is that correct?).  In that case not only we can't defer the resume (by
using a workqueue), but also we have to finish the resume within strict time
constraints (the time to leave the given C-like-state is one of the parameters
used by cpuidle governors to decide which state to choose).

On the other hand, busy waiting (by looping) in the case the state is
RPM_RESUMING is as though the callbacks were executed under a spinlock and we
happened to wait on it.  I'd prefer to avoid that.  Moreover, if the state is
RPM_SUSPENDING at the time a "fast path" resume is started, we are almost
guaranteed to violate the time constraints (by busy waiting for the suspend to
complete and carrying out the resume).

So, here's an idea:

First, let's introduce two flags in struct dev_pm_info, irq_safe and
fast_resume.  The former has to be set so that the things above work.

Second, let's add a new flag to pass to __pm_runtime_{suspend|resume}(),
RPM_FAST_RESUME such that if it is passed to __pm_runtime_suspend(), it
causes fast_resume to be set for the given device (if the status is already
RPM_SUSPENDED, it just sets the flag, otherwise it suspends the device
normally and then sets the flag).  Now, if fast_resume is set,
__pm_runtime_resume() has to be passed RPM_FAST_RESUME, or it will
fail (it also will fail if passed RPM_FAST_RESUME and fast_resume isn't
set).  In that case the status has to be RPM_SUSPENDED or RPM_RESUMING
(otherwise fast_resume won't be set) and if it is RPM_RESUMING, this means
that the other resume has been called with RPM_FAST_RESUME too (it would
fail otherwise), so it's fine to busy loop until the status is RPM_SUSPENDED
(it's the caller's problem to avoid that).  RPM_FAST_RESUME causes
__pm_runtime_resume() to avod turning interrupts on.

If necessary, there may be a flag for __pm_runtime_suspend() that will
carry out "atomic" suspend, but I'm not sure if that's necessary.  Kevin?

Rafael

^ permalink raw reply

* [PATCH] net: clear heap allocations for privileged ethtool actions
From: Kees Cook @ 2010-10-07 21:10 UTC (permalink / raw)
  To: linux-kernel
  Cc: David S. Miller, Ben Hutchings, Jeff Garzik, Jeff Kirsher,
	Peter P Waskiewicz Jr, netdev

Several other ethtool functions leave heap uncleared (potentially) by
drivers. Some interfaces appear safe (eeprom, etc), in that the sizes
are well controlled. In some situations (e.g. unchecked error conditions),
the heap will remain unchanged in areas before copying back to userspace.
Note that these are less of an issue since these all require CAP_NET_ADMIN.

Cc: stable@kernel.org
Signed-off-by: Kees Cook <kees.cook@canonical.com>
---
 net/core/ethtool.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 7a85367..fb9cf30 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -397,7 +397,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
 	    (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
 		return -ENOMEM;
 	full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
-	indir = kmalloc(full_size, GFP_USER);
+	indir = kzalloc(full_size, GFP_USER);
 	if (!indir)
 		return -ENOMEM;
 
@@ -538,7 +538,7 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
 
 	gstrings.len = ret;
 
-	data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+	data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
 	if (!data)
 		return -ENOMEM;
 
@@ -775,7 +775,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
 	if (regs.len > reglen)
 		regs.len = reglen;
 
-	regbuf = kmalloc(reglen, GFP_USER);
+	regbuf = kzalloc(reglen, GFP_USER);
 	if (!regbuf)
 		return -ENOMEM;
 
-- 
1.7.1

-- 
Kees Cook
Ubuntu Security Team

^ permalink raw reply related

* Re: [PATCH] percpu_counter: change inaccurate comment
From: Christoph Lameter @ 2010-10-07 21:06 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Andrew Morton, linux-kernel
In-Reply-To: <1286484131.3745.88.camel@edumazet-laptop>

On Thu, 7 Oct 2010, Eric Dumazet wrote:

> >
> > The only difference between __this_cpu_ptr and this_cpu_ptr is that
> > this_cpu_ptr checks that preempt was disabled. __this_cpu_ptr allows use
> > even without preempt. Preempt must be disabled here so the use of
> > this_cpu_ptr is appropriate.
> >
> >
>
> Thats not how I read the thing.
>
> In both variants, preemption _must_ be disabled, its only the context
> that can tell how sure we are...

Correct. One checks the other one does not check.

> <quote>
>
> commit 7340a0b15280c
>
> __this_cpu_ptr  -> Do not check for preemption context
> this_cpu_ptr    -> Check preemption context
>
> </quote>
>
> If preemption was enabled, both pointers would not be very useful...
>
> We use __this_cpu_ptr() in contexts where cpu _cannot_ change under us,
> (we just disabled preemption one line above), so its not necessary to
> perform the check.

Someone could screw up the code in the future. Thats what its there for.



^ permalink raw reply

* Re: [Qemu-devel] [PATCH] ceph/rbd block driver for qemu-kvm (v4)
From: Anthony Liguori @ 2010-10-07 21:04 UTC (permalink / raw)
  To: Yehuda Sadeh Weinraub
  Cc: Kevin Wolf, ceph-devel, qemu-devel, kvm, Christian Brunner
In-Reply-To: <AANLkTimW98qPTYZ=Bct7k7XqaOXswC51QdQOW6fLsWkQ@mail.gmail.com>

On 10/07/2010 03:47 PM, Yehuda Sadeh Weinraub wrote:
>> How is that possible?  Are the callbacks delivered in the context of a
>> different thread?  If so, don't you need locking?
>>      
> Not sure I'm completely following you. The callbacks are delivered in
> the context of a different thread, but won't run concurrently.

Concurrently to what?  How do you prevent them from running concurrently 
with qemu?

If you saw lock ups, I bet that's what it was from.

Regards,

Anthony Liguori

>   Do you
> see any specific concurrency issue? We can add some mutex protection
> around at the aio callback, so that if librados turns multithreaded at
> this point we're covered.
>
>
> Thanks,
> Yehuda
>
>    

^ permalink raw reply

* Re: [PATCH] serial: DCC(JTAG) serial and console emulation support
From: Mike Frysinger @ 2010-10-07 21:05 UTC (permalink / raw)
  To: Daniel Walker
  Cc: linux-kernel, Hyok S. Choi, Tony Lindgren, Jeff Ohlstein,
	Greg Kroah-Hartman, Ben Dooks, Alan Cox, Kukjin Kim, Feng Tang,
	Tobias Klauser, Jason Wessel, Philippe Langlais
In-Reply-To: <1286485186.23836.56.camel@c-dwalke-linux.qualcomm.com>

On Thu, Oct 7, 2010 at 16:59, Daniel Walker wrote:
> On Thu, 2010-10-07 at 16:47 -0400, Mike Frysinger wrote:
>> On Thu, Oct 7, 2010 at 16:06, Daniel Walker wrote:
>> > On Thu, 2010-10-07 at 16:02 -0400, Mike Frysinger wrote:
>> >> how is that any different from:
>> >> ln -s ttyJ0 /dev/ttyS0
>> >
>> > It has the same major and minors as ttyS* does. So you don't have to run
>> > anything on the target.
>>
>> i dont see how those things are related.  the major/minor are
>> irrelevant, unless you've already hard coded these in some app that
>> creates device nodes manually (instead of mdev/udev), but even then
>> that's something that "needs to be run on the target".  and both
>> already have config support to transparently do something like
>> "symlink ttyS# to XXX" as XXX is created.
>
> Something does ultimately run on all targets, the issues is does the
> person debugging have the ability to change it .. It's not always the
> case that they can change it. The userspace may not have udev at all.
> The userspace may consist of a single binary .. I'm not making any
> assumptions about the userspace here, it can be anything.

then there is already a static rootfs with pre-populated /dev which
would be fixed, or the single binary fixed.  if the options are "my
system works" or "my system doesnt work", i cant imagine people would
continue to attempt to use "/dev/ttyS#" if it didnt exist or didnt
work.
-mike

^ permalink raw reply

* Re: [PATCH 2/2] keys: added cleanup code for trusted and encrypted key types
From: Mimi Zohar @ 2010-10-07 21:05 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: keyrings, linux-crypto, David Howells, David Safford,
	Rajiv Andrade, linux-security-module
In-Reply-To: <201010071430.46281.roberto.sassu@polito.it>

Thanks for catching this! This patch applies cleanly to the
trusted/encrypted patch set posted today.

thanks,

Acked-by: Mimi Zohar <zohar@us.ibm.com>

On Thu, 2010-10-07 at 14:30 +0200, Roberto Sassu wrote:
> This patch frees the payload at the end of the instantiate
> method of both trusted and encrypted key types if an error occurs.
> 
> Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
> ---
>  security/keys/encrypted_defined.c |    6 ++++++
>  security/keys/trusted_defined.c   |    4 ++++
>  2 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/security/keys/encrypted_defined.c b/security/keys/encrypted_defined.c
> index 54c0f0f..8426e66 100644
> --- a/security/keys/encrypted_defined.c
> +++ b/security/keys/encrypted_defined.c
> @@ -624,7 +624,13 @@ static int encrypted_instantiate(struct key *key, const void *data,
>  	}
>  	ret = encrypted_init(epayload, master_desc, decrypted_datalen,
>  			     hex_encoded_iv, hex_encoded_data);
> +	if (ret)
> +		goto out_free_epayload;
> +
>  	rcu_assign_pointer(key->payload.data, epayload);
> +out_free_epayload:
> +	if (ret)
> +		kfree(epayload);
>  out:
>  	kfree(datablob);
>  	return ret > 0 ? -EINVAL : ret;
> diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
> index aedad16..ab7c7f9 100644
> --- a/security/keys/trusted_defined.c
> +++ b/security/keys/trusted_defined.c
> @@ -848,6 +848,10 @@ static int trusted_instantiate(struct key *key, const void *data,
>  out:
>  	if (!ret)
>  		rcu_assign_pointer(key->payload.data, p);
> +	else {
> +		if (p)
> +			kfree(p);
> +	}
>  	kfree(datablob);
>  	return ret;
>  }

^ permalink raw reply

* Re: [PATCH] serial: DCC(JTAG) serial and console emulation support
From: Mike Frysinger @ 2010-10-07 21:03 UTC (permalink / raw)
  To: Daniel Walker
  Cc: Alan Cox, linux-kernel, Hyok S. Choi, Tony Lindgren,
	Jeff Ohlstein, Greg Kroah-Hartman, Ben Dooks, Alan Cox,
	Kukjin Kim, Feng Tang, Tobias Klauser, Jason Wessel,
	Philippe Langlais
In-Reply-To: <1286484678.23836.49.camel@c-dwalke-linux.qualcomm.com>

On Thu, Oct 7, 2010 at 16:51, Daniel Walker wrote:
> On Thu, 2010-10-07 at 22:05 +0100, Alan Cox wrote:
>> On Thu, 07 Oct 2010 13:36:06 -0700 Daniel Walker wrote:
>> > On Thu, 2010-10-07 at 21:50 +0100, Alan Cox wrote:
>> > > > +         Say Y here if you want to install DCC driver as a normal serial port
>> > > > +         /dev/ttyS0 (major 4, minor 64). Otherwise, it appears as /dev/ttyJ0
>> > > > +         (major 4, minor 128) and can co-exist with other UARTs, such as
>> > > > +         8250/16C550 compatibles.
>> > > > +
>> > >
>> > > NAK to both
>> >
>> > I would agree if this wasn't strictly for debugging embedded devices in
>> > difficult situations.. After talking to Mike, it's seems like it would
>> > be useful to have this as a ttyS* specifically because embedded devices
>> > won't always create a ttyJ* for you and ttyS* will likely already exist.
>>
>> If you are debugging an embedded device you are capable of changing it
>> (otherwise you wouldn't debug it). Therefore the fact you might need to
>> tweak the tty creation on the device is not a problem. If you can't
>> change the device well there is no point debugging it is there !
>
> Your making too many assumptions .. You might be able to modify the
> kernel, and not the userspace. So you couldn't tweak the device
> creation .. It's much easier in the server world ..

this driver isnt in the kernel.  there is no ABI to preserve.  if
people want to use the mainline driver, they can fix their userspace.
i dont think the "binary userspace" argument is terribly relevant to
new driver submissions.
-mike

^ permalink raw reply

* Re: OT: compilation
From: Grzesiek Sójka @ 2010-10-07 21:04 UTC (permalink / raw)
  To: Xavier Chantry; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <AANLkTi=HO9rxCTOXdhagYm7WB-pF73C8_eipMCrYeGOG-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 10/07/10 22:50, Xavier Chantry wrote:
> 2010/10/7 Grzesiek Sójka<pld-t9zbU3WrWHI@public.gmane.org>:
>> I have two problems with the kernel compilation.
>>
>> 1. I have a small rootfs. It is too small to put all the modules there
>> without gzipping it first. So installing it requires lots of sweating. That
>> is why I was wondering if there is a (more/less easy) way to make the "make
>> modules_install" command gzip the modules "on the fly".
>>
>
> No idea if you can do that but here are some possible alternatives :
> 1) increase the size of your rootfs
Veeeeeeeeeeeeery difficult in my case.

> 2) remove modules you don't need and change from modules to builtin
> for features or drivers that you don't need to unload/reload
I'm trying to do this. Unfortunately I did not compile the kernel by 
myself for at lest 5 yeas and it is a big in my a%$#.

> 3) a quick googling showed me this patch :
> http://www.mail-archive.com/linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg271865.html
> However it seems to install first then compress so if that's the case,
> you will need to adapt it to your need
If I'm right it compress every module _just_after_ imstalling it. So it 
should be fine for me.

> 4) set INSTALL_MOD_PATH to a prefix , compress modules , then move to
> /lib/modules/
If 3) don't helps I try to do this.


> LOCALVERSION_AUTO is found in :
> make menuconfig
> General Setup
> Automatically append version information to the version string


Supper thanks

^ permalink raw reply

* Re: [Qemu-devel] [PATCH] ceph/rbd block driver for qemu-kvm (v4)
From: Anthony Liguori @ 2010-10-07 21:04 UTC (permalink / raw)
  To: Yehuda Sadeh Weinraub
  Cc: Kevin Wolf, kvm, qemu-devel, ceph-devel, Christian Brunner
In-Reply-To: <AANLkTimW98qPTYZ=Bct7k7XqaOXswC51QdQOW6fLsWkQ@mail.gmail.com>

On 10/07/2010 03:47 PM, Yehuda Sadeh Weinraub wrote:
>> How is that possible?  Are the callbacks delivered in the context of a
>> different thread?  If so, don't you need locking?
>>      
> Not sure I'm completely following you. The callbacks are delivered in
> the context of a different thread, but won't run concurrently.

Concurrently to what?  How do you prevent them from running concurrently 
with qemu?

If you saw lock ups, I bet that's what it was from.

Regards,

Anthony Liguori

>   Do you
> see any specific concurrency issue? We can add some mutex protection
> around at the aio callback, so that if librados turns multithreaded at
> this point we're covered.
>
>
> Thanks,
> Yehuda
>
>    


^ permalink raw reply

* Re: [PATCH 1/2] keys: fixed handling of update method of the encrypted key type
From: Mimi Zohar @ 2010-10-07 21:03 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: keyrings, linux-crypto, David Howells, David Safford,
	Rajiv Andrade, linux-security-module
In-Reply-To: <201010071429.24664.roberto.sassu@polito.it>

Nice! This patch applies cleanly to the trusted/encrypted patch set
posted today.

thanks,

Acked-by: Mimi Zohar <zohar@us.ibm.com>

On Thu, 2010-10-07 at 14:29 +0200, Roberto Sassu wrote:
> This patch adds the UPDATE keyword for encrypted key types:
> prevents updating existent keys if UPDATE is missing and creating
> new keys when UPDATE is specified.
> 
> Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
> ---
>  security/keys/encrypted_defined.c |   31 +++++++++++++++++++++++--------
>  1 files changed, 23 insertions(+), 8 deletions(-)
> 
> diff --git a/security/keys/encrypted_defined.c b/security/keys/encrypted_defined.c
> index 6b26db6..54c0f0f 100644
> --- a/security/keys/encrypted_defined.c
> +++ b/security/keys/encrypted_defined.c
> @@ -64,7 +64,8 @@ static int aes_get_sizes(int *ivsize, int *blksize)
>  }
>  
>  enum {
> -	Opt_err = -1, Opt_new = 1, Opt_load, Opt_NEW, Opt_LOAD
> +	Opt_err = -1, Opt_new = 1, Opt_load, 
> +	Opt_update, Opt_NEW, Opt_LOAD, Opt_UPDATE
>  };
>  
>  static match_table_t key_tokens = {
> @@ -72,6 +73,8 @@ static match_table_t key_tokens = {
>  	{Opt_NEW, "NEW"},
>  	{Opt_load, "load"},
>  	{Opt_LOAD, "LOAD"},
> +	{Opt_update, "update"},
> +	{Opt_UPDATE, "UPDATE"},
>  	{Opt_err, NULL}
>  };
>  
> @@ -81,6 +84,7 @@ static match_table_t key_tokens = {
>   * datablob format:
>   * NEW <master-key name> <decrypted data length>
>   * LOAD <master-key name> <decrypted data length> <encrypted iv + data>
> + * UPDATE <new-master-key name>
>   *
>   * Tokenizes a copy of the keyctl data, returning a pointer to each token,
>   * which is null terminated.
> @@ -104,23 +108,36 @@ static int datablob_parse(char *datablob, char **master_desc,
>  	*master_desc = strsep(&datablob, " \t");
>  	if (!*master_desc)
>  		goto out;
> -	*decrypted_datalen = strsep(&datablob, " \t");
> -	if (!*decrypted_datalen)
> -		goto out;
> +
> +	if (decrypted_datalen) {
> +		*decrypted_datalen = strsep(&datablob, " \t");
> +		if (!*decrypted_datalen)
> +			goto out;
> +	}
>  
>  	switch (key_cmd) {
>  	case Opt_new:
>  	case Opt_NEW:
> +		if (!decrypted_datalen)
> +			break;
>  		ret = 0;
>  		break;
>  	case Opt_load:
>  	case Opt_LOAD:
> +		if (!decrypted_datalen)
> +			break;
>  		*hex_encoded_iv = strsep(&datablob, " \t");
>  		if (!*hex_encoded_iv)
>  			break;
>  		*hex_encoded_data = *hex_encoded_iv + (2 * ivsize) + 2;
>  		ret = 0;
>  		break;
> +	case Opt_update:
> +	case Opt_UPDATE:
> +		if (decrypted_datalen)
> +			break;
> +		ret = 0;
> +		break;
>  	case Opt_err:
>  		break;
>  	}
> @@ -647,11 +664,9 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
>  		return -ENOMEM;
>  
>  	memcpy(buf, data, datalen);
> -	new_master_desc = strsep(&buf, " \t");
> -	if (!*new_master_desc) {
> -		ret = -EINVAL;
> +	ret = datablob_parse(buf, &new_master_desc, NULL, NULL, NULL);
> +	if (ret < 0)
>  		goto out;
> -	}
>  
>  	new_epayload = encrypted_key_alloc(key, new_master_desc,
>  					   epayload->datalen);

^ permalink raw reply

* Re: [PATCH] mac80211: hoist sta->lock from reorder release timer
From: Johannes Berg @ 2010-10-07 21:03 UTC (permalink / raw)
  To: John W. Linville
  Cc: Christian Lamparter, linux-wireless, Ben Greear, Ming Lei
In-Reply-To: <20101006202106.GL2472@tuxdriver.com>

On Wed, 2010-10-06 at 16:21 -0400, John W. Linville wrote:

> > I think it's probably easier to fix than to revert now? There are only a
> > handful of fields, and it seemed to me that most of them can easily be
> > moved under the reorder lock.
> 
> I would prefer a fix on top rather than a series of reverts...

I think this should fix it. Somebody review please?

johannes

---
 net/mac80211/agg-rx.c      |    8 +++-----
 net/mac80211/debugfs_sta.c |   29 +++++++++++++++--------------
 net/mac80211/rx.c          |   17 +++++++++++++----
 net/mac80211/sta_info.h    |   29 ++++++++++++++---------------
 4 files changed, 45 insertions(+), 38 deletions(-)

--- wireless-testing.orig/net/mac80211/agg-rx.c	2010-10-07 22:44:04.000000000 +0200
+++ wireless-testing/net/mac80211/agg-rx.c	2010-10-07 22:53:33.000000000 +0200
@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_exp
 			timer_to_tid[0]);
 
 	rcu_read_lock();
-	spin_lock(&sta->lock);
 	ieee80211_release_reorder_timeout(sta, *ptid);
-	spin_unlock(&sta->lock);
 	rcu_read_unlock();
 }
 
@@ -256,7 +254,7 @@ void ieee80211_process_addba_request(str
 	}
 
 	/* prepare A-MPDU MLME for Rx aggregation */
-	tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
+	tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
 	if (!tid_agg_rx) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		if (net_ratelimit())
@@ -280,9 +278,9 @@ void ieee80211_process_addba_request(str
 
 	/* prepare reordering buffer */
 	tid_agg_rx->reorder_buf =
-		kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC);
+		kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL);
 	tid_agg_rx->reorder_time =
-		kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC);
+		kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
 	if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		if (net_ratelimit())
--- wireless-testing.orig/net/mac80211/debugfs_sta.c	2010-10-07 22:47:41.000000000 +0200
+++ wireless-testing/net/mac80211/debugfs_sta.c	2010-10-07 22:50:03.000000000 +0200
@@ -116,34 +116,35 @@ static ssize_t sta_agg_status_read(struc
 	char buf[71 + STA_TID_NUM * 40], *p = buf;
 	int i;
 	struct sta_info *sta = file->private_data;
+	struct tid_ampdu_rx *tid_rx;
+	struct tid_ampdu_tx *tid_tx;
+
+	rcu_read_lock();
 
-	spin_lock_bh(&sta->lock);
 	p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
 			sta->ampdu_mlme.dialog_token_allocator + 1);
 	p += scnprintf(p, sizeof(buf) + buf - p,
 		       "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
+
 	for (i = 0; i < STA_TID_NUM; i++) {
+		tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
+		tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
+
 		p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
-		p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
-				!!sta->ampdu_mlme.tid_rx[i]);
+		p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx);
 		p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
-				sta->ampdu_mlme.tid_rx[i] ?
-				sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
+				tid_rx ? tid_rx->dialog_token : 0);
 		p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
-				sta->ampdu_mlme.tid_rx[i] ?
-				sta->ampdu_mlme.tid_rx[i]->ssn : 0);
+				tid_rx ? tid_rx->ssn : 0);
 
-		p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
-				!!sta->ampdu_mlme.tid_tx[i]);
+		p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_tx);
 		p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
-				sta->ampdu_mlme.tid_tx[i] ?
-				sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
+				tid_tx ? tid_tx->dialog_token : 0);
 		p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
-				sta->ampdu_mlme.tid_tx[i] ?
-				skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0);
+				tid_tx ? skb_queue_len(&tid_tx->pending) : 0);
 		p += scnprintf(p, sizeof(buf) + buf - p, "\n");
 	}
-	spin_unlock_bh(&sta->lock);
+	rcu_read_unlock();
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 }
--- wireless-testing.orig/net/mac80211/sta_info.h	2010-10-07 22:44:16.000000000 +0200
+++ wireless-testing/net/mac80211/sta_info.h	2010-10-07 23:01:53.000000000 +0200
@@ -81,13 +81,14 @@ enum ieee80211_sta_info_flags {
  * @stop_initiator: initiator of a session stop
  * @tx_stop: TX DelBA frame when stopping
  *
- * This structure is protected by RCU and the per-station
- * spinlock. Assignments to the array holding it must hold
- * the spinlock, only the TX path can access it under RCU
- * lock-free if, and only if, the state has  the flag
- * %HT_AGG_STATE_OPERATIONAL set. Otherwise, the TX path
- * must also acquire the spinlock and re-check the state,
- * see comments in the tx code touching it.
+ * This structure's lifetime is managed by RCU, assignments to
+ * the array holding it must hold the aggregation mutex.
+ *
+ * The TX path can access it under RCU lock-free if, and
+ * only if, the state has the flag %HT_AGG_STATE_OPERATIONAL
+ * set. Otherwise, the TX path must also acquire the spinlock
+ * and re-check the state, see comments in the tx code
+ * touching it.
  */
 struct tid_ampdu_tx {
 	struct rcu_head rcu_head;
@@ -115,15 +116,13 @@ struct tid_ampdu_tx {
  * @rcu_head: RCU head used for freeing this struct
  * @reorder_lock: serializes access to reorder buffer, see below.
  *
- * This structure is protected by RCU and the per-station
- * spinlock. Assignments to the array holding it must hold
- * the spinlock.
+ * This structure's lifetime is managed by RCU, assignments to
+ * the array holding it must hold the aggregation mutex.
  *
- * The @reorder_lock is used to protect the variables and
- * arrays such as @reorder_buf, @reorder_time, @head_seq_num,
- * @stored_mpdu_num and @reorder_time from being corrupted by
- * concurrent access of the RX path and the expired frame
- * release timer.
+ * The @reorder_lock is used to protect the members of this
+ * struct, except for @timeout, @buf_size and @dialog_token,
+ * which are constant across the lifetime of the struct (the
+ * dialog token being used only for debugging).
  */
 struct tid_ampdu_rx {
 	struct rcu_head rcu_head;
--- wireless-testing.orig/net/mac80211/rx.c	2010-10-07 22:52:03.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c	2010-10-07 22:58:17.000000000 +0200
@@ -538,6 +538,8 @@ static void ieee80211_release_reorder_fr
 {
 	struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
 
+	lockdep_assert_held(&tid_agg_rx->reorder_lock);
+
 	if (!skb)
 		goto no_frame;
 
@@ -557,6 +559,8 @@ static void ieee80211_release_reorder_fr
 {
 	int index;
 
+	lockdep_assert_held(&tid_agg_rx->reorder_lock);
+
 	while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
 		index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
 							tid_agg_rx->buf_size;
@@ -581,6 +585,8 @@ static void ieee80211_sta_reorder_releas
 {
 	int index, j;
 
+	lockdep_assert_held(&tid_agg_rx->reorder_lock);
+
 	/* release the buffer until next missing frame */
 	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
 						tid_agg_rx->buf_size;
@@ -659,10 +665,11 @@ static bool ieee80211_sta_manage_reorder
 	int index;
 	bool ret = true;
 
+	spin_lock(&tid_agg_rx->reorder_lock);
+
 	buf_size = tid_agg_rx->buf_size;
 	head_seq_num = tid_agg_rx->head_seq_num;
 
-	spin_lock(&tid_agg_rx->reorder_lock);
 	/* frame with out of date sequence number */
 	if (seq_less(mpdu_seq_num, head_seq_num)) {
 		dev_kfree_skb(skb);
@@ -1899,9 +1906,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_
 			mod_timer(&tid_agg_rx->session_timer,
 				  TU_TO_EXP_TIME(tid_agg_rx->timeout));
 
+		spin_lock(&tid_agg_rx->reorder_lock);
 		/* release stored frames up to start of BAR */
 		ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
 						 frames);
+		spin_unlock(&tid_agg_rx->reorder_lock);
+
 		kfree_skb(skb);
 		return RX_QUEUED;
 	}
@@ -2493,9 +2503,8 @@ static void ieee80211_invoke_rx_handlers
 }
 
 /*
- * This function makes calls into the RX path. Therefore the
- * caller must hold the sta_info->lock and everything has to
- * be under rcu_read_lock protection as well.
+ * This function makes calls into the RX path, therefore
+ * it has to be invoked under RCU read lock.
  */
 void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
 {



^ permalink raw reply

* Re: bttv: No analogue sound output by TV card
From: Mauro Carvalho Chehab @ 2010-10-07 21:01 UTC (permalink / raw)
  To: Richard Atterer; +Cc: linux-media
In-Reply-To: <20101007205540.GA3640@arbonne.lan>

Em 07-10-2010 17:55, Richard Atterer escreveu:
> Hello,
> 
> my problem is still present in 2.6.36-rc7, the log output is unchanged from 
> rc5.
> 
> All the best,
>   Richard
> 
> On Fri, Oct 01, 2010 at 12:19:53AM +0200, Richard Atterer wrote:
>> [Please CC me, I'm not on the list.]
>>
>> Hi,
>>
>> after switching from 2.6.34 to 2.6.36-rc5, the sound on my old Hauppauge 
>> analogue TV card has stopped working. Audio out from the TV card is 
>> connected to line-in of my motherboard (Gigabyte EG45M-DS2H) using the 
>> short cable that came with the TV card. Other audio sources (e.g. MP3 
>> player) are audible when connected to line-in. The TV picture is fine.
>>
>> The log messages look really similar for the two kernels.
>>
>> 2.6.34 works:
>> kernel: bttv: driver version 0.9.18 loaded
>> kernel: bttv: using 8 buffers with 2080k (520 pages) each for capture
>> kernel: bttv: Bt8xx card found (0).
>> kernel: bttv0: Bt878 (rev 17) at 0000:03:01.0, irq: 19, latency: 32, mmio: 0xe3600000
>> kernel: bttv0: detected: Hauppauge WinTV [card=10], PCI subsystem ID is 0070:13eb
>> kernel: bttv0: using: Hauppauge (bt878) [card=10,autodetected]
>> kernel: IRQ 19/bttv0: IRQF_DISABLED is not guaranteed on shared IRQs
>> kernel: bttv0: gpio: en=00000000, out=00000000 in=00ffffdb [init]
>> kernel: bttv0: Hauppauge/Voodoo msp34xx: reset line init [5]
>> kernel: tveeprom 1-0050: Hauppauge model 44354, rev D147, serial# 1234567
>> kernel: tveeprom 1-0050: tuner model is LG TP18PSB01D (idx 47, type 28)
>> kernel: tveeprom 1-0050: TV standards PAL(B/G) (eeprom 0x04)
>> kernel: tveeprom 1-0050: audio processor is MSP3415 (idx 6)
>> kernel: tveeprom 1-0050: has radio
>> kernel: bttv0: Hauppauge eeprom indicates model#44354
>> kernel: bttv0: tuner type=28
>> kernel: msp3400 1-0040: MSP3415D-B3 found @ 0x80 (bt878 #0 [sw])
>> kernel: msp3400 1-0040: msp3400 supports nicam, mode is autodetect
>> kernel: tuner 1-0061: chip found @ 0xc2 (bt878 #0 [sw])
>> kernel: tuner-simple 1-0061: creating new instance
>> kernel: tuner-simple 1-0061: type set to 28 (LG PAL_BG+FM (TPI8PSB01D))
>> kernel: bttv0: registered device video0
>> kernel: bttv0: registered device vbi0
>> kernel: bttv0: registered device radio0
>> kernel: bttv0: PLL: 28636363 => 35468950 .
>> kernel: bttv0: PLL: 28636363 => 35468950 . ok
>> kernel:  ok
>>
>> 2.6.36-rc5 does not work:
>> kernel: bttv: driver version 0.9.18 loaded
>> kernel: bttv: using 8 buffers with 2080k (520 pages) each for capture
>> kernel: bttv: Bt8xx card found (0).
>> kernel: bttv0: Bt878 (rev 17) at 0000:03:01.0, irq: 19, latency: 32, mmio: 0xe3600000
>> kernel: bttv0: detected: Hauppauge WinTV [card=10], PCI subsystem ID is 0070:13eb
>> kernel: bttv0: using: Hauppauge (bt878) [card=10,autodetected]
>> kernel: bttv0: gpio: en=00000000, out=00000000 in=00ffffdb [init]
>> kernel: bttv0: Hauppauge/Voodoo msp34xx: reset line init [5]
>> kernel: tveeprom 1-0050: Hauppauge model 44354, rev D147, serial# 1234567
>> kernel: tveeprom 1-0050: tuner model is LG TP18PSB01D (idx 47, type 28)
>> kernel: tveeprom 1-0050: TV standards PAL(B/G) (eeprom 0x04)
>> kernel: tveeprom 1-0050: audio processor is MSP3415 (idx 6)
>> kernel: tveeprom 1-0050: has radio
>> kernel: bttv0: Hauppauge eeprom indicates model#44354
>> kernel: bttv0: tuner type=28
>> kernel: msp3400 1-0040: MSP3415D-B3 found @ 0x80 (bt878 #0 [sw])
>> kernel: msp3400 1-0040: msp3400 supports nicam, mode is autodetect
>> kernel: tuner 1-0061: chip found @ 0xc2 (bt878 #0 [sw])
>> kernel: tuner-simple 1-0061: creating new instance
>> kernel: tuner-simple 1-0061: type set to 28 (LG PAL_BG+FM (TPI8PSB01D))
>> kernel: bttv0: registered device video0
>> kernel: bttv0: registered device vbi0
>> kernel: bttv0: registered device radio0
>> kernel: bttv0: PLL: 28636363 => 35468950 . ok
>>
>> The only real change is that the IRQF_DISABLED warning is gone.
> 

I can't remember of any functional changes at sound stuff that might cause such trouble.

The better would be if you could bisect what patch broke it and point it to us.

Thanks,
Mauro

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-07 21:01 UTC (permalink / raw)
  To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101007152626.4e834d43@udp111988uds.am.freescale.net>

> On Thu, 7 Oct 2010 15:12:26 -0500.
>
> BTW, the MSIs are already described in an msi node in the device tree.
As far as I can tell, ONLY in root complex mode, not in endpoint mode,
which is what I am working with.

What I want is a means by which the system root complex can generate one
or more interrupts INTO the 8641 when it is operating in endpoint mode.

^ permalink raw reply

* Re: [PATCH] serial: DCC(JTAG) serial and console emulation support
From: Daniel Walker @ 2010-10-07 20:59 UTC (permalink / raw)
  To: Mike Frysinger
  Cc: linux-kernel, Hyok S. Choi, Tony Lindgren, Jeff Ohlstein,
	Greg Kroah-Hartman, Ben Dooks, Alan Cox, Kukjin Kim, Feng Tang,
	Tobias Klauser, Jason Wessel, Philippe Langlais
In-Reply-To: <AANLkTinDvL9vPb6nmve3rO9dMtMAqh=d1oqBVTOHzYWH@mail.gmail.com>

On Thu, 2010-10-07 at 16:47 -0400, Mike Frysinger wrote:
> On Thu, Oct 7, 2010 at 16:06, Daniel Walker wrote:
> > On Thu, 2010-10-07 at 16:02 -0400, Mike Frysinger wrote:
> >> how is that any different from:
> >> ln -s ttyJ0 /dev/ttyS0
> >
> > It has the same major and minors as ttyS* does. So you don't have to run
> > anything on the target.
> 
> i dont see how those things are related.  the major/minor are
> irrelevant, unless you've already hard coded these in some app that
> creates device nodes manually (instead of mdev/udev), but even then
> that's something that "needs to be run on the target".  and both
> already have config support to transparently do something like
> "symlink ttyS# to XXX" as XXX is created.

Something does ultimately run on all targets, the issues is does the
person debugging have the ability to change it .. It's not always the
case that they can change it. The userspace may not have udev at all.
The userspace may consist of a single binary .. I'm not making any
assumptions about the userspace here, it can be anything.

Daniel

-- 

Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply

* Re: [PATCH 2/2] sched: use the old min_vruntime when normalizing on dequeue
From: Dima Zavin @ 2010-10-07 21:00 UTC (permalink / raw)
  To: linux-kernel
  Cc: Peter Zijlstra, Ingo Molnar, Mike Galbraith, Dima Zavin,
	Arve Hjønnevåg
In-Reply-To: <1285742774-5013-2-git-send-email-dima@android.com>

Mike,

Thanks for the Ack for patch 1/2, could you take a look at this one too?

Should I re-upload the series as v2 or you can pick the latest from
patch 1 and take this one?

--Dima

On Tue, Sep 28, 2010 at 11:46 PM, Dima Zavin <dima@android.com> wrote:
> After pulling the thread off the run-queue during a cgroup change,
> the cfs_rq.min_vruntime gets recalculated. The dequeued thread's vruntime
> then gets normalized to this new value. This can then lead to the thread
> getting an unfair boost in the new group if the vruntime of the next
> task in the old run-queue was way further ahead.
>
> Cc: Arve Hjønnevåg <arve@android.com>
> Signed-off-by: Dima Zavin <dima@android.com>
> ---
>  kernel/sched_fair.c |    6 +++++-
>  1 files changed, 5 insertions(+), 1 deletions(-)
>
> diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
> index 008fe57..cb24ddb 100644
> --- a/kernel/sched_fair.c
> +++ b/kernel/sched_fair.c
> @@ -802,6 +802,8 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
>  static void
>  dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
>  {
> +       u64 min_vruntime;
> +
>        /*
>         * Update run-time statistics of the 'current'.
>         */
> @@ -826,6 +828,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
>        if (se != cfs_rq->curr)
>                __dequeue_entity(cfs_rq, se);
>        account_entity_dequeue(cfs_rq, se);
> +
> +       min_vruntime = cfs_rq->min_vruntime;
>        update_min_vruntime(cfs_rq);
>
>        /*
> @@ -834,7 +838,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
>         * movement in our normalized position.
>         */
>        if (!(flags & DEQUEUE_SLEEP))
> -               se->vruntime -= cfs_rq->min_vruntime;
> +               se->vruntime -= min_vruntime;
>  }
>
>  /*
> --
> 1.6.6
>
>

^ permalink raw reply

* Re: [PATCH 1/2] drivers:staging:ti-st: move TI_ST from staging
From: Alan Cox @ 2010-10-07 20:59 UTC (permalink / raw)
  To: Savoy, Pavan
  Cc: Jiri Slaby, gregkh@suse.de, linux-kernel@vger.kernel.org,
	devel@driverdev.osuosl.org, linux-bluetooth@vger.kernel.org
In-Reply-To: <19F8576C6E063C45BE387C64729E739404AA21D248@dbde02.ent.ti.com>

> But, I want to attach my data not when ldsic is opened, but when ldisc is registered.
> I want to begin accessing the data when ldisc is opened.

How can you attach per tty data when the ldisc is registered - the
relevant tty driver might not even have been loaded at that point. The
user may not even have been to the shop and bought it even !

What sort of data is this ?

> to be like a bunch of helpers (1 for FM, 1 for GPS, 1 for NFC, 1 for power-management), also the problem of who owns the /dev/tty begins to occur, Bluetooth has a utility called hciattach, I don't want my FM radio software to run hciattach when /dev/radio0 is opened and communicated via FM.

I would have assumed the hotplug script would have run your own attach
and daemon and the FM radio etc would talk to the ldisc via other kernel
interfaces it presented.

So whenever the hardware is detected it would load the hardware driver
The hardware driver would create a tty instance for each physical port
The hotplug user space would run 'ti-st-attach' as a helper which would
load the ldisc and set up the bluetooth as well as providing exported
methods for FM radio etc.

> In any case, the ti-st/ seems better now by look of things, I certainly welcome suggestions to improve it.
> Also, is there any plan to re-write whole of TTY like a the i2C or the SPI bus structure?
> 
> Here I can imagine, all TTY line disciplines being sort of protocol/client drivers, the TTY sub-system in itself would be like the algos driver and then
> The uart drivers (like 8250.c) can be the adapter drivers.. What say?

They already are, with the one oddity being that something needs to have
it opened from user space and to attach the ldisc. Thats fixable but hard
to fix and I'm not aware of any plan to do so - mostly because nobody
needs it so far.

Alan

^ permalink raw reply

* Re: [PATCH net-next-2.6] net: Fix rxq ref counting
From: Eric Dumazet @ 2010-10-07 20:59 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, netdev
In-Reply-To: <alpine.DEB.1.00.1010071304240.4792@pokey.mtv.corp.google.com>

Le jeudi 07 octobre 2010 à 13:09 -0700, Tom Herbert a écrit :
> The rx->count reference is used to track reference counts to the
> number of rx-queue kobjects created for the device.  This patch
> eliminates initialization of the counter in netif_alloc_rx_queues
> and instead increments the counter each time a kobject is created.
> This is now symmetric with the decrement that is done when an object is
> released.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 7d14955..58b31d1 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -5026,7 +5026,6 @@ static int netif_alloc_rx_queues(struct net_device *dev)
>  			return -ENOMEM;
>  		}
>  		dev->_rx = rx;
> -		atomic_set(&rx->count, count);
>  
>  		/*
>  		 * Set a pointer to first element in the array which holds the
> diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
> index fa81fd0..b143173 100644
> --- a/net/core/net-sysfs.c
> +++ b/net/core/net-sysfs.c
> @@ -726,6 +726,7 @@ static struct kobj_type rx_queue_ktype = {
>  static int rx_queue_add_kobject(struct net_device *net, int index)
>  {
>  	struct netdev_rx_queue *queue = net->_rx + index;
> +	struct netdev_rx_queue *first = queue->first;
>  	struct kobject *kobj = &queue->kobj;
>  	int error = 0;
>  
> @@ -738,6 +739,7 @@ static int rx_queue_add_kobject(struct net_device *net, int index)
>  	}
>  
>  	kobject_uevent(kobj, KOBJ_ADD);
> +	atomic_inc(&first->count);
>  
>  	return error;
>  }

Acked-by: Eric Dumazet <eric.dumazet@gmail.com>




^ permalink raw reply

* Re: [PATCH net-next-2.6] net: Fix rxq ref counting
From: Eric Dumazet @ 2010-10-07 20:56 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, netdev
In-Reply-To: <alpine.DEB.1.00.1010071304240.4792@pokey.mtv.corp.google.com>

Le jeudi 07 octobre 2010 à 13:09 -0700, Tom Herbert a écrit :
> The rx->count reference is used to track reference counts to the
> number of rx-queue kobjects created for the device.  This patch
> eliminates initialization of the counter in netif_alloc_rx_queues
> and instead increments the counter each time a kobject is created.
> This is now symmetric with the decrement that is done when an object is
> released.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 7d14955..58b31d1 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -5026,7 +5026,6 @@ static int netif_alloc_rx_queues(struct net_device *dev)
>  			return -ENOMEM;
>  		}
>  		dev->_rx = rx;
> -		atomic_set(&rx->count, count);
>  
>  		/*
>  		 * Set a pointer to first element in the array which holds the
> diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
> index fa81fd0..b143173 100644
> --- a/net/core/net-sysfs.c
> +++ b/net/core/net-sysfs.c
> @@ -726,6 +726,7 @@ static struct kobj_type rx_queue_ktype = {
>  static int rx_queue_add_kobject(struct net_device *net, int index)
>  {
>  	struct netdev_rx_queue *queue = net->_rx + index;
> +	struct netdev_rx_queue *first = queue->first;
>  	struct kobject *kobj = &queue->kobj;
>  	int error = 0;
>  
> @@ -738,6 +739,7 @@ static int rx_queue_add_kobject(struct net_device *net, int index)
>  	}
>  
>  	kobject_uevent(kobj, KOBJ_ADD);
> +	atomic_inc(&first->count);
>  
>  	return error;
>  }

Acked-by: Eric Dumazet <eric.dumazet@gmail.com>



^ permalink raw reply

* Re: bttv: No analogue sound output by TV card
From: Richard Atterer @ 2010-10-07 20:55 UTC (permalink / raw)
  To: mchehab; +Cc: linux-media
In-Reply-To: <20100930221953.GA7062@arbonne.lan>

Hello,

my problem is still present in 2.6.36-rc7, the log output is unchanged from 
rc5.

All the best,
  Richard

On Fri, Oct 01, 2010 at 12:19:53AM +0200, Richard Atterer wrote:
> [Please CC me, I'm not on the list.]
> 
> Hi,
> 
> after switching from 2.6.34 to 2.6.36-rc5, the sound on my old Hauppauge 
> analogue TV card has stopped working. Audio out from the TV card is 
> connected to line-in of my motherboard (Gigabyte EG45M-DS2H) using the 
> short cable that came with the TV card. Other audio sources (e.g. MP3 
> player) are audible when connected to line-in. The TV picture is fine.
> 
> The log messages look really similar for the two kernels.
> 
> 2.6.34 works:
> kernel: bttv: driver version 0.9.18 loaded
> kernel: bttv: using 8 buffers with 2080k (520 pages) each for capture
> kernel: bttv: Bt8xx card found (0).
> kernel: bttv0: Bt878 (rev 17) at 0000:03:01.0, irq: 19, latency: 32, mmio: 0xe3600000
> kernel: bttv0: detected: Hauppauge WinTV [card=10], PCI subsystem ID is 0070:13eb
> kernel: bttv0: using: Hauppauge (bt878) [card=10,autodetected]
> kernel: IRQ 19/bttv0: IRQF_DISABLED is not guaranteed on shared IRQs
> kernel: bttv0: gpio: en=00000000, out=00000000 in=00ffffdb [init]
> kernel: bttv0: Hauppauge/Voodoo msp34xx: reset line init [5]
> kernel: tveeprom 1-0050: Hauppauge model 44354, rev D147, serial# 1234567
> kernel: tveeprom 1-0050: tuner model is LG TP18PSB01D (idx 47, type 28)
> kernel: tveeprom 1-0050: TV standards PAL(B/G) (eeprom 0x04)
> kernel: tveeprom 1-0050: audio processor is MSP3415 (idx 6)
> kernel: tveeprom 1-0050: has radio
> kernel: bttv0: Hauppauge eeprom indicates model#44354
> kernel: bttv0: tuner type=28
> kernel: msp3400 1-0040: MSP3415D-B3 found @ 0x80 (bt878 #0 [sw])
> kernel: msp3400 1-0040: msp3400 supports nicam, mode is autodetect
> kernel: tuner 1-0061: chip found @ 0xc2 (bt878 #0 [sw])
> kernel: tuner-simple 1-0061: creating new instance
> kernel: tuner-simple 1-0061: type set to 28 (LG PAL_BG+FM (TPI8PSB01D))
> kernel: bttv0: registered device video0
> kernel: bttv0: registered device vbi0
> kernel: bttv0: registered device radio0
> kernel: bttv0: PLL: 28636363 => 35468950 .
> kernel: bttv0: PLL: 28636363 => 35468950 . ok
> kernel:  ok
> 
> 2.6.36-rc5 does not work:
> kernel: bttv: driver version 0.9.18 loaded
> kernel: bttv: using 8 buffers with 2080k (520 pages) each for capture
> kernel: bttv: Bt8xx card found (0).
> kernel: bttv0: Bt878 (rev 17) at 0000:03:01.0, irq: 19, latency: 32, mmio: 0xe3600000
> kernel: bttv0: detected: Hauppauge WinTV [card=10], PCI subsystem ID is 0070:13eb
> kernel: bttv0: using: Hauppauge (bt878) [card=10,autodetected]
> kernel: bttv0: gpio: en=00000000, out=00000000 in=00ffffdb [init]
> kernel: bttv0: Hauppauge/Voodoo msp34xx: reset line init [5]
> kernel: tveeprom 1-0050: Hauppauge model 44354, rev D147, serial# 1234567
> kernel: tveeprom 1-0050: tuner model is LG TP18PSB01D (idx 47, type 28)
> kernel: tveeprom 1-0050: TV standards PAL(B/G) (eeprom 0x04)
> kernel: tveeprom 1-0050: audio processor is MSP3415 (idx 6)
> kernel: tveeprom 1-0050: has radio
> kernel: bttv0: Hauppauge eeprom indicates model#44354
> kernel: bttv0: tuner type=28
> kernel: msp3400 1-0040: MSP3415D-B3 found @ 0x80 (bt878 #0 [sw])
> kernel: msp3400 1-0040: msp3400 supports nicam, mode is autodetect
> kernel: tuner 1-0061: chip found @ 0xc2 (bt878 #0 [sw])
> kernel: tuner-simple 1-0061: creating new instance
> kernel: tuner-simple 1-0061: type set to 28 (LG PAL_BG+FM (TPI8PSB01D))
> kernel: bttv0: registered device video0
> kernel: bttv0: registered device vbi0
> kernel: bttv0: registered device radio0
> kernel: bttv0: PLL: 28636363 => 35468950 . ok
> 
> The only real change is that the IRQF_DISABLED warning is gone.

-- 
  __   ,
  | ) /|  Richard Atterer
  | \/ |  http://atterer.org


^ permalink raw reply

* Re: [PATCH] dell-laptop: Add hwswitch_only module parameter
From: Mario Limonciello @ 2010-10-07 20:53 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Keng-Yu Lin, len.brown, alan-jenkins, platform-driver-x86,
	linux-kernel
In-Reply-To: <20101007205049.GB32726@srcf.ucam.org>

Hi Matthew:

On Thu, Oct 7, 2010 at 15:50, Matthew Garrett <mjg@redhat.com> wrote:
> On Thu, Oct 07, 2010 at 03:49:05PM -0500, Mario Limonciello wrote:
>> Hi Matthew:
>> > Is the kernel able to unblock it under those circumstances?
>>
>> Manually running rfkill unblock will unblock it in this broken
>> firmware scenario in question.
>
> So the issue is in the firmware's response to the keystroke? Ok. I'd
> rather have a DMI list of the broken machines than a module parameter.

Yes the issue is the firmware's response to the keystroke.  The
intention here is to individual submit machines in future patches as
they're discovered.  The parameter's primary purpose is to assist in
building the list.  If someone reports a bug with these symptoms, they
can add the parameter to their kernel command line, and report if it
helps them.  If it helps, their machine can be added to the DMI table.

-- 
Mario Limonciello
superm1@gmail.com

^ permalink raw reply

* [PATCH v1 4/4] keys: add new key-type encrypted
From: Mimi Zohar @ 2010-10-07 20:52 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mimi Zohar, linux-security-module, keyrings, linux-crypto,
	David Howells, James Morris, David Safford, Rajiv Andrade,
	Mimi Zohar
In-Reply-To: <1286484734-3119-1-git-send-email-zohar@linux.vnet.ibm.com>

Defines a new kernel key-type called 'encrypted'. Encrypted keys are
kernel generated random numbers, which are encrypted/decrypted with
a 'trusted' symmetric key. Encrypted keys are created/encrypted/decrypted
in the kernel.  Userspace only ever sees/stores encrypted blobs.

Changelog:
- wait until late_initcall for crypto libraries to be registered
- cleanup security/Kconfig

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Signed-off-by: David Safford <safford@watson.ibm.com>
---
 include/keys/encrypted-type.h     |   30 ++
 security/Kconfig                  |   16 +
 security/keys/Makefile            |    1 +
 security/keys/encrypted_defined.c |  782 +++++++++++++++++++++++++++++++++++++
 security/keys/encrypted_defined.h |   52 +++
 5 files changed, 881 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h

diff --git a/include/keys/encrypted-type.h b/include/keys/encrypted-type.h
new file mode 100644
index 0000000..e2312e0
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,30 @@
+/* encrypted-type.h: encrypted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+#ifndef _KEYS_ENCRYPTED_TYPE_H
+#define _KEYS_ENCRYPTED_TYPE_H
+
+#include <linux/key.h>
+#include <linux/rcupdate.h>
+
+struct encrypted_key_payload {
+	struct rcu_head rcu;	/* RCU destructor */
+	char *master_desc;	/* datablob: master key name */
+	char *datalen;		/* datablob: decrypted key length */
+	void *iv;		/* datablob: iv */
+	void *encrypted_data;	/* datablob: encrypted key */
+	unsigned short datablob_len;	/* length of datablob */
+	unsigned short decrypted_datalen;	/* decrypted data length */
+	char decrypted_data[0];	/* decrypted data +  datablob + hmac */
+};
+
+extern struct key_type key_type_encrypted;
+
+#endif /* _KEYS_ENCRYPTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index 38fdaf6..d591398 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -36,6 +36,22 @@ config TRUSTED_KEYS
 
 	  If you are unsure as to whether this is required, answer N.
 
+config ENCRYPTED_KEYS
+	tristate "ENCRYPTED KEYS"
+	depends on KEYS && TRUSTED_KEYS
+	select CRYPTO_AES
+	select CRYPTO_CBC
+	select CRYPTO_SHA256
+	select CRYPTO_RNG
+	help
+	  This option provides support for create/encrypting/decrypting keys
+	  in the kernel.  Encrypted keys are kernel generated random numbers,
+	  which are encrypted/decrypted with a 'master' symmetric key. The
+	  'master' key can be either a trusted-key or user-key type.
+	  Userspace only ever sees/stores encrypted blobs.
+
+	  If you are unsure as to whether this is required, answer N.
+
 config KEYS_DEBUG_PROC_KEYS
 	bool "Enable the /proc/keys file by which keys may be viewed"
 	depends on KEYS
diff --git a/security/keys/Makefile b/security/keys/Makefile
index fcb1070..6c94105 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -14,6 +14,7 @@ obj-y := \
 	user_defined.o
 
 obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
+obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/encrypted_defined.c b/security/keys/encrypted_defined.c
new file mode 100644
index 0000000..68fff82
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * File: encrypted_defined.c
+ *
+ * Defines a new kernel key-type called 'encrypted'. Encrypted keys
+ * are kernel generated random numbers, which are encrypted/decrypted
+ * using a 'master' key. The 'master' key can either be a trusted-key or
+ * user-key type. Encrypted keys are created/encrypted/decrypted in the
+ * kernel. Userspace ever only sees/stores encrypted blobs.
+ *
+ * keyctl add "encrypted" "name" "NEW master-key-name keylen" ring
+ * keyctl add "encrypted" "name" "LOAD master-key-name keylen hex_blob" ring
+ * keyctl update keyid "UPDATE master-key-name"
+ */
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <keys/trusted-type.h>
+#include <keys/encrypted-type.h>
+#include <linux/key-type.h>
+#include <linux/random.h>
+#include <linux/rcupdate.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/sha.h>
+#include <crypto/aes.h>
+
+#include "encrypted_defined.h"
+
+static char hash_alg[] = "sha256";
+static char hmac_alg[] = "hmac(sha256)";
+static int hash_size = SHA256_DIGEST_SIZE;
+static char blkcipher_alg[] = "cbc(aes)";
+static int ivsize;
+static int blksize;
+
+static int aes_get_sizes(int *ivsize, int *blksize)
+{
+	struct crypto_blkcipher *tfm;
+
+	tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		pr_err("encrypted_key: failed to alloc_cipher (%ld)\n",
+		       PTR_ERR(tfm));
+		return PTR_ERR(tfm);
+	}
+	*ivsize = crypto_blkcipher_ivsize(tfm);
+	*blksize = crypto_blkcipher_blocksize(tfm);
+	crypto_free_blkcipher(tfm);
+	return 0;
+}
+
+enum {
+	Opt_err = -1, Opt_new = 1, Opt_load, Opt_NEW, Opt_LOAD
+};
+
+static match_table_t key_tokens = {
+	{Opt_new, "new"},
+	{Opt_NEW, "NEW"},
+	{Opt_load, "load"},
+	{Opt_LOAD, "LOAD"},
+	{Opt_err, NULL}
+};
+
+/*
+ * datablob_parse - parse the keyctl data
+ *
+ * datablob format:
+ * NEW <master-key name> <decrypted data length>
+ * LOAD <master-key name> <decrypted data length> <encrypted iv + data>
+ *
+ * Tokenizes a copy of the keyctl data, returning a pointer to each token,
+ * which is null terminated.
+ *
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int datablob_parse(char *datablob, char **master_desc,
+			  char **decrypted_datalen, char **hex_encoded_iv,
+			  char **hex_encoded_data)
+{
+	substring_t args[MAX_OPT_ARGS];
+	int ret = -EINVAL;
+	int key_cmd;
+	char *p;
+
+	p = strsep(&datablob, " \t");
+	if (!p)
+		return ret;
+	key_cmd = match_token(p, key_tokens, args);
+
+	*master_desc = strsep(&datablob, " \t");
+	if (!*master_desc)
+		goto out;
+	*decrypted_datalen = strsep(&datablob, " \t");
+	if (!*decrypted_datalen)
+		goto out;
+
+	switch (key_cmd) {
+	case Opt_new:
+	case Opt_NEW:
+		ret = 0;
+		break;
+	case Opt_load:
+	case Opt_LOAD:
+		*hex_encoded_iv = strsep(&datablob, " \t");
+		if (!*hex_encoded_iv)
+			break;
+		*hex_encoded_data = *hex_encoded_iv + (2 * ivsize) + 2;
+		ret = 0;
+		break;
+	case Opt_err:
+		break;
+	}
+out:
+	return ret;
+}
+
+/* datablob_format - format as an ascii string, before copying to userspace */
+static int datablob_format(char __user *buffer,
+			   struct encrypted_key_payload *epayload,
+			   int asciiblob_len)
+{
+	char *ascii_buf, *bufp;
+	char *iv = (char *)epayload->iv;
+	int ret = 0;
+	int len;
+	int i;
+
+	ascii_buf = kzalloc(asciiblob_len + 1, GFP_KERNEL);
+	if (!ascii_buf)
+		return -ENOMEM;
+
+	len = sprintf(ascii_buf, "%s %s ", epayload->master_desc,
+		      epayload->datalen);
+
+	/* convert the hex encoded iv, encrypted-data and HMAC to ascii */
+	bufp = &ascii_buf[len];
+	for (i = 0; i < (asciiblob_len - len) / 2; i++)
+		bufp = pack_hex_byte(bufp, iv[i]);
+
+	if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0)
+		ret = -EFAULT;
+	kfree(ascii_buf);
+	return ret;
+}
+
+/*
+ * request_trusted_key - request the trusted key
+ *
+ * Trusted keys are sealed to PCRs and other metadata. Although userspace
+ * manages both trusted/encrypted key-types, like the encrypted key type
+ * data, trusted key type data is not visible decrypted from userspace.
+ */
+static struct key *request_trusted_key(char *trusted_desc, void **master_key,
+				       unsigned int *master_keylen)
+{
+	struct trusted_key_payload *tpayload;
+	struct key *tkey;
+
+	tkey = request_key(&key_type_trusted, trusted_desc, NULL);
+	if (IS_ERR(tkey))
+		goto error;
+
+	tpayload = tkey->payload.data;
+	*master_key = tpayload->key;
+	*master_keylen = tpayload->key_len;
+error:
+	return tkey;
+}
+
+/*
+ * request_user_key - request the user key
+ *
+ * Use a user provided key to encrypt/decrypt an encrypted-key.
+ */
+static struct key *request_user_key(char *master_desc, void **master_key,
+				    unsigned int *master_keylen)
+{
+	struct user_key_payload *upayload;
+	struct key *ukey;
+
+	ukey = request_key(&key_type_user, master_desc, NULL);
+	if (IS_ERR(ukey))
+		goto error;
+
+	upayload = ukey->payload.data;
+	*master_key = upayload->data;
+	*master_keylen = (unsigned int)upayload->datalen;
+error:
+	return ukey;
+}
+
+static int init_desc(struct hash_desc *desc, char *alg)
+{
+	int ret;
+
+	desc->tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc->tfm)) {
+		pr_info("encrypted_key: failed to load %s transform: %ld\n",
+			alg, PTR_ERR(desc->tfm));
+		ret = PTR_ERR(desc->tfm);
+		return ret;
+	}
+	desc->flags = 0;
+	ret = crypto_hash_init(desc);
+	if (ret)
+		crypto_free_hash(desc->tfm);
+	return ret;
+}
+
+static int calc_hmac(char *digest, char *key, int keylen,
+		     char *buf, size_t buflen)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	int ret;
+
+	ret = init_desc(&desc, hmac_alg);
+	if (ret)
+		return ret;
+
+	crypto_hash_setkey(desc.tfm, key, keylen);
+	ret = crypto_hash_init(&desc);
+	if (ret)
+		goto out;
+
+	sg_init_one(sg, buf, buflen);
+	ret = crypto_hash_update(&desc, sg, buflen);
+	if (!ret)
+		ret = crypto_hash_final(&desc, digest);
+out:
+	crypto_free_hash(desc.tfm);
+	return ret;
+}
+
+static int calc_hash(char *digest, void *buf, int buflen)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	int ret;
+
+	ret = init_desc(&desc, hash_alg);
+	if (ret)
+		return ret;
+
+	sg_init_one(sg, buf, buflen);
+	ret = crypto_hash_update(&desc, sg, buflen);
+	if (!ret)
+		ret = crypto_hash_final(&desc, digest);
+	crypto_free_hash(desc.tfm);
+	return ret;
+}
+
+enum derived_key_type { ENC_KEY, AUTH_KEY };
+
+/* Derive authentication/encryption key from trusted key */
+static int get_derived_key(char *derived_key, enum derived_key_type key_type,
+			   void *master_key, unsigned int master_keylen)
+{
+	char derived_buf[hash_size + 10];
+	int ret;
+
+	memset(derived_buf, 0, sizeof derived_buf);
+	if (key_type)
+		strcpy(derived_buf, "AUTH_KEY");
+	else
+		strcpy(derived_buf, "ENC_KEY");
+
+	memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
+	       master_keylen);
+	ret = calc_hash(derived_key, derived_buf, sizeof derived_buf);
+	return ret;
+}
+
+static int init_blkcipher_desc(struct blkcipher_desc *desc, const void *key,
+			       unsigned int key_len, void *iv, int ivsize)
+{
+	int ret;
+
+	desc->tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc->tfm)) {
+		pr_err("encrypted_key: failed to load %s transform (%ld)\n",
+		       blkcipher_alg, PTR_ERR(desc->tfm));
+		return PTR_ERR(desc->tfm);
+	}
+	desc->flags = 0;
+
+	ret = crypto_blkcipher_setkey(desc->tfm, key, key_len);
+	if (ret) {
+		pr_err("encrypted_key: failed to setkey (%d)\n", ret);
+		crypto_free_blkcipher(desc->tfm);
+		return ret;
+	}
+	crypto_blkcipher_set_iv(desc->tfm, iv, ivsize);
+	return 0;
+}
+
+static struct key *request_master_key(struct encrypted_key_payload *epayload,
+				      void **master_key,
+				      unsigned int *master_keylen)
+{
+	struct key *mkey;
+
+	mkey = request_trusted_key(epayload->master_desc,
+				   master_key, master_keylen);
+	if (IS_ERR(mkey)) {
+		mkey = request_user_key(epayload->master_desc,
+					master_key, master_keylen);
+		if (IS_ERR(mkey)) {
+			pr_info("encrypted_key: trusted/user key %s not found",
+				epayload->master_desc);
+			return mkey;
+		}
+	}
+	dump_master_key(*master_key, *master_keylen);
+	return mkey;
+}
+
+/* Before returning data to userspace, encrypt decrypted data. */
+static int derived_key_encrypt(struct encrypted_key_payload *epayload,
+			       void *derived_key, unsigned int derived_keylen)
+{
+	struct scatterlist sg_in[2];
+	struct scatterlist sg_out[1];
+	struct blkcipher_desc desc;
+	unsigned int encrypted_datalen;
+	unsigned int padlen;
+	char pad[16];
+	int ret;
+
+	encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
+	padlen = encrypted_datalen - epayload->decrypted_datalen;
+
+	ret = init_blkcipher_desc(&desc, derived_key, derived_keylen,
+				  epayload->iv, ivsize);
+	if (ret)
+		goto out;
+	dump_decrypted_data(epayload);
+
+	memset(pad, 0, sizeof pad);
+	sg_init_table(sg_in, 2);
+	sg_set_buf(&sg_in[0], epayload->decrypted_data,
+		   epayload->decrypted_datalen);
+	sg_set_buf(&sg_in[1], pad, padlen);
+
+	sg_init_table(sg_out, 1);
+	sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
+
+	ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, encrypted_datalen);
+	crypto_free_blkcipher(desc.tfm);
+	if (ret)
+		pr_err("encrypted_key: failed to encrypt (%d)\n", ret);
+	else
+		dump_encrypted_data(epayload, encrypted_datalen);
+out:
+	return ret;
+}
+
+static int datablob_hmac_append(struct encrypted_key_payload *epayload,
+				void *master_key, unsigned int master_keylen)
+{
+	char derived_key[hash_size];
+	char *digest;
+	int ret;
+
+	memset(derived_key, 0, sizeof derived_key);
+	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
+	if (ret)
+		goto out;
+
+	digest = epayload->master_desc + epayload->datablob_len;
+	ret = calc_hmac(digest, derived_key, sizeof derived_key,
+			epayload->master_desc, epayload->datablob_len);
+	if (!ret)
+		dump_hmac(NULL, digest, hash_size);
+out:
+	return ret;
+}
+
+/* verify HMAC before decrypting encrypted key */
+static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
+				void *master_key, unsigned int master_keylen)
+{
+	char derived_key[hash_size];
+	char digest[hash_size];
+	int ret;
+
+	memset(derived_key, 0, sizeof derived_key);
+	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
+	if (ret)
+		goto out;
+
+	memset(digest, 0, sizeof digest);
+	ret = calc_hmac(digest, derived_key, sizeof derived_key,
+			epayload->master_desc, epayload->datablob_len);
+	if (ret)
+		goto out;
+	ret = memcmp(digest, epayload->master_desc + epayload->datablob_len,
+		     sizeof digest);
+	if (ret) {
+		dump_hmac("datablob",
+			  epayload->master_desc + epayload->datablob_len,
+			  hash_size);
+		dump_hmac("calc", digest, hash_size);
+	}
+out:
+	return ret;
+}
+
+static int derived_key_decrypt(struct encrypted_key_payload *epayload,
+			       void *derived_key, unsigned int derived_keylen)
+{
+	struct scatterlist sg_in[1];
+	struct scatterlist sg_out[2];
+	struct blkcipher_desc desc;
+	unsigned int encrypted_datalen;
+	char pad[16];
+	int ret;
+
+	encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
+	ret = init_blkcipher_desc(&desc, derived_key, derived_keylen,
+				  epayload->iv, ivsize);
+	if (ret)
+		goto out;
+	dump_encrypted_data(epayload, encrypted_datalen);
+
+	memset(pad, 0, sizeof pad);
+	sg_init_table(sg_in, 1);
+	sg_init_table(sg_out, 2);
+	sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen);
+	sg_set_buf(&sg_out[0], epayload->decrypted_data,
+		   (unsigned int)epayload->decrypted_datalen);
+	sg_set_buf(&sg_out[1], pad, sizeof pad);
+
+	ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, encrypted_datalen);
+	crypto_free_blkcipher(desc.tfm);
+	if (ret)
+		goto out;
+	dump_decrypted_data(epayload);
+out:
+	return ret;
+}
+
+/* Allocate memory for decrypted key and datablob. */
+static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
+							 const char *master_desc,
+							 char *datalen)
+{
+	struct encrypted_key_payload *epayload = NULL;
+	unsigned short datablob_len;
+	unsigned short decrypted_datalen;
+	size_t encrypted_datalen;
+	long dlen;
+	int ret;
+
+	ret = strict_strtol(datalen, 10, &dlen);
+	if (ret < 0 || dlen < 20 || dlen > hash_size)
+		return ERR_PTR(-EINVAL);
+
+	decrypted_datalen = (unsigned short)dlen;
+	encrypted_datalen = roundup(decrypted_datalen, blksize);
+
+	datablob_len = strlen(master_desc) + 1 + strlen(datalen) + 1
+	    + ivsize + 1 + encrypted_datalen;
+
+	ret = key_payload_reserve(key, decrypted_datalen + datablob_len
+				  + hash_size + 1);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	epayload = kzalloc(sizeof(*epayload) + decrypted_datalen +
+			   datablob_len + hash_size + 1, GFP_KERNEL);
+	if (!epayload)
+		return ERR_PTR(-ENOMEM);
+
+	epayload->decrypted_datalen = decrypted_datalen;
+	epayload->datablob_len = datablob_len;
+	return epayload;
+}
+
+static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
+				 char *hex_encoded_iv, char *hex_encoded_data)
+{
+	char derived_key[hash_size];
+	struct key *mkey;
+	void *master_key;
+	unsigned int master_keylen;
+	size_t encrypted_datalen;
+	char *hmac;
+	int ret;
+
+	encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
+	hex2bin(epayload->iv, hex_encoded_iv, ivsize);
+	hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen);
+
+	hmac = epayload->master_desc + epayload->datablob_len;
+	hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), hash_size);
+
+	mkey = request_master_key(epayload, &master_key, &master_keylen);
+	if (IS_ERR(mkey))
+		return PTR_ERR(mkey);
+
+	ret = datablob_hmac_verify(epayload, master_key, master_keylen);
+	if (ret) {
+		pr_err("encrypted_key: bad hmac (%d)\n", ret);
+		goto out;
+	}
+
+	memset(derived_key, 0, sizeof derived_key);
+	ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
+	if (ret)
+		goto out;
+
+	ret = derived_key_decrypt(epayload, derived_key, sizeof derived_key);
+	if (ret)
+		pr_err("encrypted_key: failed to decrypt key (%d)\n", ret);
+out:
+	key_put(mkey);
+	return ret;
+}
+
+static void __ekey_init(struct encrypted_key_payload *epayload,
+			char *master_desc, char *datalen)
+{
+	epayload->master_desc = epayload->decrypted_data
+	    + epayload->decrypted_datalen;
+	epayload->datalen = epayload->master_desc + strlen(master_desc) + 1;
+	epayload->iv = epayload->datalen + strlen(datalen) + 1;
+	epayload->encrypted_data = epayload->iv + ivsize + 1;
+
+	memcpy(epayload->master_desc, master_desc, strlen(master_desc));
+	memcpy(epayload->datalen, datalen, strlen(datalen));
+}
+
+/*
+ * encrypted_init - initialize an encrypted key
+ *
+ * For a new key, use a random number for both the iv and data
+ * itself.  For an old key, decrypt the hex encoded data.
+ */
+static int encrypted_init(struct encrypted_key_payload *epayload,
+			  char *master_desc, char *datalen,
+			  char *hex_encoded_iv, char *hex_encoded_data)
+{
+	int ret = 0;
+
+	__ekey_init(epayload, master_desc, datalen);
+	if (!hex_encoded_data) {
+		get_random_bytes(epayload->iv, ivsize);
+
+		get_random_bytes(epayload->decrypted_data,
+				 epayload->decrypted_datalen);
+	} else
+		ret = encrypted_key_decrypt(epayload, hex_encoded_iv,
+					    hex_encoded_data);
+	return ret;
+}
+
+/*
+ * encrypted_instantiate - instantiate an encrypted key
+ *
+ * Decrypt an existing encrypted datablob or create a new encrypted key
+ * based on a kernel random number.
+ *
+ * On success, return 0. Otherwise return errno.
+ */
+static int encrypted_instantiate(struct key *key, const void *data,
+				 size_t datalen)
+{
+	struct encrypted_key_payload *epayload = NULL;
+	char *datablob = NULL;
+	char *master_desc = NULL;
+	char *decrypted_datalen = NULL;
+	char *hex_encoded_iv = NULL;
+	char *hex_encoded_data = NULL;
+	int ret;
+
+	if (datalen <= 0 || datalen > 32767 || !data)
+		return -EINVAL;
+
+	datablob = kzalloc(datalen + 1, GFP_KERNEL);
+	if (!datablob)
+		return -ENOMEM;
+
+	memcpy(datablob, data, datalen);
+	ret = datablob_parse(datablob, &master_desc, &decrypted_datalen,
+			     &hex_encoded_iv, &hex_encoded_data);
+	if (ret < 0)
+		goto out;
+
+	epayload = encrypted_key_alloc(key, master_desc, decrypted_datalen);
+	if (IS_ERR(epayload)) {
+		ret = PTR_ERR(epayload);
+		goto out;
+	}
+	ret = encrypted_init(epayload, master_desc, decrypted_datalen,
+			     hex_encoded_iv, hex_encoded_data);
+	rcu_assign_pointer(key->payload.data, epayload);
+out:
+	kfree(datablob);
+	return ret > 0 ? -EINVAL : ret;
+}
+
+static void encrypted_rcu_free(struct rcu_head *rcu)
+{
+	struct encrypted_key_payload *epayload;
+
+	epayload = container_of(rcu, struct encrypted_key_payload, rcu);
+	memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
+	kfree(epayload);
+}
+
+/*
+ * encrypted_update - update the master key description
+ *
+ * Change the master key description for an existing encrypted key.
+ * The next read will return an encrypted datablob using the new
+ * master key description.
+ *
+ * On success, return 0. Otherwise return errno.
+ */
+static int encrypted_update(struct key *key, const void *data, size_t datalen)
+{
+	struct encrypted_key_payload *epayload = key->payload.data;
+	struct encrypted_key_payload *new_epayload;
+	char *buf;
+	char *new_master_desc = NULL;
+	int ret = 0;
+
+	if (datalen <= 0 || datalen > 32767 || !data)
+		return -EINVAL;
+
+	buf = kzalloc(datalen + 1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	memcpy(buf, data, datalen);
+	new_master_desc = strsep(&buf, " \t");
+	if (!*new_master_desc) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	new_epayload = encrypted_key_alloc(key, new_master_desc,
+					   epayload->datalen);
+	if (IS_ERR(new_epayload)) {
+		ret = PTR_ERR(new_epayload);
+		goto out;
+	}
+
+	__ekey_init(new_epayload, new_master_desc, epayload->datalen);
+
+	memcpy(new_epayload->iv, epayload->iv, ivsize);
+	memcpy(new_epayload->decrypted_data, epayload->decrypted_data,
+	       epayload->decrypted_datalen);
+
+	rcu_assign_pointer(key->payload.data, new_epayload);
+	call_rcu(&epayload->rcu, encrypted_rcu_free);
+out:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * encrypted_read - format and copy the encrypted data to userspace
+ *
+ * The resulting datablob format is:
+ * <master-key name> <decrypted data length> <encrypted iv> <encrypted data>
+ *
+ * On success, return to userspace the encrypted key datablob size.
+ */
+static long encrypted_read(const struct key *key, char __user * buffer,
+			   size_t buflen)
+{
+	struct encrypted_key_payload *epayload;
+	struct key *mkey;
+	void *master_key;
+	unsigned int master_keylen;
+	char derived_key[hash_size];
+	int asciiblob_len;
+	int ret;
+
+	epayload = rcu_dereference_protected(key->payload.data,
+				  rwsem_is_locked(&((struct key *)key)->sem));
+
+	/* returns the hex encoded iv, encrypted-data, and hmac as ascii */
+	asciiblob_len = epayload->datablob_len + ivsize + 1
+	    + roundup(epayload->decrypted_datalen, blksize)
+	    + (hash_size * 2);
+
+	if (!buffer || buflen <= 0)
+		return asciiblob_len;
+
+	mkey = request_master_key(epayload, &master_key, &master_keylen);
+	if (IS_ERR(mkey))
+		return PTR_ERR(mkey);
+
+	memset(derived_key, 0, sizeof derived_key);
+	ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
+	if (ret)
+		goto out;
+
+	ret = derived_key_encrypt(epayload, derived_key, sizeof derived_key);
+	if (ret)
+		goto out;
+
+	ret = datablob_hmac_append(epayload, master_key, master_keylen);
+	if (ret)
+		goto out;
+
+	ret = datablob_format(buffer, epayload, asciiblob_len);
+	if (ret < 0)
+		goto out;
+
+	key_put(mkey);
+	return asciiblob_len;
+out:
+	key_put(mkey);
+	return ret > 0 ? -EINVAL : ret;
+}
+
+/*
+ * encrypted_destroy - before freeing the key, clear the decrypted data
+ *
+ * Before freeing the key, clear the memory containing the descrypted
+ * key data.
+ */
+static void encrypted_destroy(struct key *key)
+{
+	struct encrypted_key_payload *epayload = key->payload.data;
+
+	if (!epayload)
+		return;
+
+	memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
+	kfree(key->payload.data);
+}
+
+struct key_type key_type_encrypted = {
+	.name = "encrypted",
+	.instantiate = encrypted_instantiate,
+	.update = encrypted_update,
+	.match = user_match,
+	.destroy = encrypted_destroy,
+	.describe = user_describe,
+	.read = encrypted_read,
+};
+EXPORT_SYMBOL_GPL(key_type_encrypted);
+
+static int __init init_encrypted(void)
+{
+	int ret;
+
+	ret = register_key_type(&key_type_encrypted);
+	if (ret < 0)
+		return ret;
+	ret = aes_get_sizes(&ivsize, &blksize);
+	return ret;
+}
+
+static void __exit cleanup_encrypted(void)
+{
+	unregister_key_type(&key_type_encrypted);
+}
+
+late_initcall(init_encrypted);
+module_exit(cleanup_encrypted);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/encrypted_defined.h b/security/keys/encrypted_defined.h
new file mode 100644
index 0000000..4e0b6e5
--- /dev/null
+++ b/security/keys/encrypted_defined.h
@@ -0,0 +1,52 @@
+#ifndef __ENCRYPTED_KEY_H
+#define __ENCRYPTED_KEY_H
+
+#define ENCRYPTED_DEBUG 0
+
+#if ENCRYPTED_DEBUG
+static inline void dump_master_key(void *master_key, unsigned int master_keylen)
+{
+	print_hex_dump(KERN_ERR, "master key: ", DUMP_PREFIX_NONE, 32, 1,
+		       master_key, (size_t) master_keylen, 0);
+}
+
+static inline void dump_decrypted_data(struct encrypted_key_payload *epayload)
+{
+	print_hex_dump(KERN_ERR, "decrypted data: ", DUMP_PREFIX_NONE, 32, 1,
+		       epayload->decrypted_data,
+		       epayload->decrypted_datalen, 0);
+}
+
+static inline void dump_encrypted_data(struct encrypted_key_payload *epayload,
+				       unsigned int encrypted_datalen)
+{
+	print_hex_dump(KERN_ERR, "encrypted data: ", DUMP_PREFIX_NONE, 32, 1,
+		       epayload->encrypted_data, (size_t) encrypted_datalen, 0);
+}
+
+static inline void dump_hmac(char *str, void *digest, unsigned int hmac_size)
+{
+	if (str)
+		pr_info("encrypted_key: %s", str);
+	print_hex_dump(KERN_ERR, "hmac: ", DUMP_PREFIX_NONE, 32, 1, digest,
+		       (size_t) hmac_size, 0);
+}
+#else
+static inline void dump_master_key(void *master_key, unsigned int master_keylen)
+{
+}
+
+static inline void dump_decrypted_data(struct encrypted_key_payload *epayload)
+{
+}
+
+static inline void dump_encrypted_data(struct encrypted_key_payload *epayload,
+				       unsigned int encrypted_datalen)
+{
+}
+
+static inline void dump_hmac(char *str, void *digest, int hmac_size)
+{
+}
+#endif
+#endif
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH v1 2/4] key: add tpm_send command
From: Mimi Zohar @ 2010-10-07 20:52 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mimi Zohar, linux-security-module, keyrings, linux-crypto,
	David Howells, James Morris, David Safford, Rajiv Andrade
In-Reply-To: <1286484734-3119-1-git-send-email-zohar@linux.vnet.ibm.com>

Add internal kernel tpm_send() command used to seal/unseal keys.

Signed-off-by: David Safford <safford@watson.ibm.com>
Reviewd-by: Mimi Zohar <zohar@watson.ibm.com>
Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
---
 drivers/char/tpm/tpm.c |   17 +++++++++++++++++
 include/linux/tpm.h    |    3 +++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..5987d9c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,23 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
 
+int tpm_send(u32 chip_num, char *cmd, int buflen)
+{
+	struct tpm_chip *chip;
+	int rc;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+
+	rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+			  "attempting tpm_cmd");
+
+	module_put(chip->dev->driver->owner);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_send);
+
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index ac5d1c1..a0ecaa9 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -31,6 +31,7 @@
 
 extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
+extern int tpm_send(u32 chip_num, char *cmd, int buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
 	return -ENODEV;
@@ -38,5 +39,7 @@ static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
 static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
 	return -ENODEV;
 }
+static inline int tpm_send(u32 chip_num, char *cmd, int buflen) {
+	return -ENODEV;
 #endif
 #endif
-- 
1.7.2.2

^ permalink raw reply related


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.