Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Sergey Senozhatsky
On (03/16/17 14:51), Minchan Kim wrote:
[..]
> > > @@ -1414,7 +1414,7 @@ static bool try_to_unmap_one(struct page *page, 
> > > struct vm_area_struct *vma,
> > >*/
> > >   if (unlikely(PageSwapBacked(page) != 
> > > PageSwapCache(page))) {
> > >   WARN_ON_ONCE(1);
> > > - ret = SWAP_FAIL;
> > > + ret = false;
> > >   page_vma_mapped_walk_done();
> > >   break;
> > >   }
> > 
> > 
> > one thing to notice here is that 'ret = false' and 'ret = SWAP_FAIL'
> > are not the same and must produce different results. `ret' is bool
> > and SWAP_FAIL was 2. it's return 1 vs return 0, isn't it? so was
> > there a bug before?
> 
> No, it was not a bug. Just my patchset changed return value meaning.
> Look at this.
> https://marc.info/?l=linux-mm=14892314806=2
> 
> So, false means SWAP_FAIL(ie., stop rmap scanning and bail out) now.

ah, indeed. sorry, didn't notice that.

thanks.

-ss


Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Sergey Senozhatsky
On (03/16/17 14:51), Minchan Kim wrote:
[..]
> > > @@ -1414,7 +1414,7 @@ static bool try_to_unmap_one(struct page *page, 
> > > struct vm_area_struct *vma,
> > >*/
> > >   if (unlikely(PageSwapBacked(page) != 
> > > PageSwapCache(page))) {
> > >   WARN_ON_ONCE(1);
> > > - ret = SWAP_FAIL;
> > > + ret = false;
> > >   page_vma_mapped_walk_done();
> > >   break;
> > >   }
> > 
> > 
> > one thing to notice here is that 'ret = false' and 'ret = SWAP_FAIL'
> > are not the same and must produce different results. `ret' is bool
> > and SWAP_FAIL was 2. it's return 1 vs return 0, isn't it? so was
> > there a bug before?
> 
> No, it was not a bug. Just my patchset changed return value meaning.
> Look at this.
> https://marc.info/?l=linux-mm=14892314806=2
> 
> So, false means SWAP_FAIL(ie., stop rmap scanning and bail out) now.

ah, indeed. sorry, didn't notice that.

thanks.

-ss


linux-next: tty: BUG: spinlock bad magic on CPU#0, init/1

2017-03-15 Thread Andrei Vagin
Hello,

We run CRIU tests for linux-next and here is a new bug in the kernel log

[2.431229] Freeing unused kernel memory: 1356K
[2.436371] Freeing unused kernel memory: 168K
[2.522236] BUG: spinlock bad magic on CPU#0, init/1
[2.527487]  lock: 0x94915477fd88, .magic: , .owner:
/-1, .owner_cpu: -1
[2.537257] CPU: 0 PID: 1 Comm: init Not tainted 4.11.0-rc1-next-20170310 #1
[2.541136] Hardware name: Google Google Compute Engine/Google
Compute Engine, BIOS Google 01/01/2011
[2.541136] Call Trace:
[2.541136]  dump_stack+0x85/0xc9
[2.541136]  spin_bug+0xa6/0xad
[2.541136]  do_raw_spin_lock+0x66/0xa0
[2.541136]  _raw_spin_lock+0x40/0x50
[2.541136]  ? check_tty_count+0x27/0xe0
[2.541136]  check_tty_count+0x27/0xe0
[2.541136]  tty_release+0x64/0x620
[2.541136]  __fput+0xfa/0x230
[2.541136]  fput+0xe/0x10
[2.541136]  task_work_run+0x83/0xc0
[2.541136]  exit_to_usermode_loop+0x64/0x9a
[2.541136]  syscall_return_slowpath+0xa9/0xe0
[2.541136]  entry_SYSCALL_64_fastpath+0xc0/0xc2
[2.541136] RIP: 0033:0x7fb953f58e10
[2.541136] RSP: 002b:7fff3d276ba8 EFLAGS: 0246 ORIG_RAX:
0003
[2.541136] RAX:  RBX: 5610f1867710 RCX: 7fb953f58e10
[2.541136] RDX: fe80 RSI: 0001 RDI: 0002
[2.541136] RBP:  R08: 5610f165786e R09: 5610f21bef90
[2.541136] R10: 000a R11: 0246 R12: 0001
[2.541136] R13: 5610f1867674 R14: 5610f1867678 R15: 0001
[2.748104] tsc: Refined TSC clocksource calibration: 2299.999 MHz

All logs are here:
https://s3.amazonaws.com/archive.travis-ci.org/jobs/211615735/log.txt

Thanks,
Andrei


linux-next: tty: BUG: spinlock bad magic on CPU#0, init/1

2017-03-15 Thread Andrei Vagin
Hello,

We run CRIU tests for linux-next and here is a new bug in the kernel log

[2.431229] Freeing unused kernel memory: 1356K
[2.436371] Freeing unused kernel memory: 168K
[2.522236] BUG: spinlock bad magic on CPU#0, init/1
[2.527487]  lock: 0x94915477fd88, .magic: , .owner:
/-1, .owner_cpu: -1
[2.537257] CPU: 0 PID: 1 Comm: init Not tainted 4.11.0-rc1-next-20170310 #1
[2.541136] Hardware name: Google Google Compute Engine/Google
Compute Engine, BIOS Google 01/01/2011
[2.541136] Call Trace:
[2.541136]  dump_stack+0x85/0xc9
[2.541136]  spin_bug+0xa6/0xad
[2.541136]  do_raw_spin_lock+0x66/0xa0
[2.541136]  _raw_spin_lock+0x40/0x50
[2.541136]  ? check_tty_count+0x27/0xe0
[2.541136]  check_tty_count+0x27/0xe0
[2.541136]  tty_release+0x64/0x620
[2.541136]  __fput+0xfa/0x230
[2.541136]  fput+0xe/0x10
[2.541136]  task_work_run+0x83/0xc0
[2.541136]  exit_to_usermode_loop+0x64/0x9a
[2.541136]  syscall_return_slowpath+0xa9/0xe0
[2.541136]  entry_SYSCALL_64_fastpath+0xc0/0xc2
[2.541136] RIP: 0033:0x7fb953f58e10
[2.541136] RSP: 002b:7fff3d276ba8 EFLAGS: 0246 ORIG_RAX:
0003
[2.541136] RAX:  RBX: 5610f1867710 RCX: 7fb953f58e10
[2.541136] RDX: fe80 RSI: 0001 RDI: 0002
[2.541136] RBP:  R08: 5610f165786e R09: 5610f21bef90
[2.541136] R10: 000a R11: 0246 R12: 0001
[2.541136] R13: 5610f1867674 R14: 5610f1867678 R15: 0001
[2.748104] tsc: Refined TSC clocksource calibration: 2299.999 MHz

All logs are here:
https://s3.amazonaws.com/archive.travis-ci.org/jobs/211615735/log.txt

Thanks,
Andrei


Re: [PATCH v3 4/7] xen/9pfs: connect to the backend

2017-03-15 Thread Juergen Gross
On 15/03/17 19:44, Stefano Stabellini wrote:
> On Wed, 15 Mar 2017, Juergen Gross wrote:
>> On 14/03/17 22:22, Stefano Stabellini wrote:
>>> Hi Juergen,
>>>
>>> thank you for the review!
>>>
>>> On Tue, 14 Mar 2017, Juergen Gross wrote:
 On 14/03/17 00:50, Stefano Stabellini wrote:
> Implement functions to handle the xenbus handshake. Upon connection,
> allocate the rings according to the protocol specification.
>
> Initialize a work_struct and a wait_queue. The work_struct will be used
> to schedule work upon receiving an event channel notification from the
> backend. The wait_queue will be used to wait when the ring is full and
> we need to send a new request.
>
> Signed-off-by: Stefano Stabellini 
> CC: boris.ostrov...@oracle.com
> CC: jgr...@suse.com
> CC: Eric Van Hensbergen 
> CC: Ron Minnich 
> CC: Latchesar Ionkov 
> CC: v9fs-develo...@lists.sourceforge.net
> ---
>>
 Did you think about using request_threaded_irq() instead of a workqueue?
 For an example see e.g. drivers/scsi/xen-scsifront.c
>>>
>>> I like workqueues :-)  It might come down to personal preferences, but I
>>> think workqueues are more flexible and a better fit for this use case.
>>> Not only it is easy to schedule work in a workqueue from the interrupt
>>> handler, but also they can be used for sleeping in the request function
>>> if there is not enough room on the ring. Besides, they can easily be
>>> configured to share a single thread or to have multiple independent
>>> threads.
>>
>> I'm fine with the workqueues as long as you have decided to use them
>> considering the alternatives. :-)
>>
 Can't you use xenbus_read_unsigned() instead of xenbus_read()?
>>>
>>> I can use xenbus_read_unsigned in the other cases below, but not here,
>>> because versions is in the form: "1,3,4"
>>
>> Is this documented somewhere?
>>
>> Hmm, are any of the Xenstore entries documented? Shouldn't this be done
>> in xen_9pfs.h ?
>  
> They are documented in docs/misc/9pfs.markdown, under "Xenstore". Given
> that it's all written there, especially the semantics, I didn't repeat
> it in xen_9pfs.h

Looking at it from the Linux kernel perspective this documentation is
not really highly visible. For me it is okay, but there have been
multiple examples in the past where documentation in the Xen repository
wasn't regarded as being sufficient.

I recommend moving the documentation regarding the interface into the
header file like for the other pv interfaces.


Juergen



Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 05:53 PM, Peter Zijlstra wrote:

On Wed, Mar 15, 2017 at 05:20:15PM +1100, Michael Ellerman wrote:


I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?

I am not indeed. That and a completely inadequate Changelog have lead to
great confusion.


Yes. my bad. I will send out a v3 today and will CC. Also will add
ellerman's explanation to the commit message.

Sorry for the confusion.

Maddy




Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 05:53 PM, Peter Zijlstra wrote:

On Wed, Mar 15, 2017 at 05:20:15PM +1100, Michael Ellerman wrote:


I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?

I am not indeed. That and a completely inadequate Changelog have lead to
great confusion.


Yes. my bad. I will send out a v3 today and will CC. Also will add
ellerman's explanation to the commit message.

Sorry for the confusion.

Maddy




Re: [PATCH v3 4/7] xen/9pfs: connect to the backend

2017-03-15 Thread Juergen Gross
On 15/03/17 19:44, Stefano Stabellini wrote:
> On Wed, 15 Mar 2017, Juergen Gross wrote:
>> On 14/03/17 22:22, Stefano Stabellini wrote:
>>> Hi Juergen,
>>>
>>> thank you for the review!
>>>
>>> On Tue, 14 Mar 2017, Juergen Gross wrote:
 On 14/03/17 00:50, Stefano Stabellini wrote:
> Implement functions to handle the xenbus handshake. Upon connection,
> allocate the rings according to the protocol specification.
>
> Initialize a work_struct and a wait_queue. The work_struct will be used
> to schedule work upon receiving an event channel notification from the
> backend. The wait_queue will be used to wait when the ring is full and
> we need to send a new request.
>
> Signed-off-by: Stefano Stabellini 
> CC: boris.ostrov...@oracle.com
> CC: jgr...@suse.com
> CC: Eric Van Hensbergen 
> CC: Ron Minnich 
> CC: Latchesar Ionkov 
> CC: v9fs-develo...@lists.sourceforge.net
> ---
>>
 Did you think about using request_threaded_irq() instead of a workqueue?
 For an example see e.g. drivers/scsi/xen-scsifront.c
>>>
>>> I like workqueues :-)  It might come down to personal preferences, but I
>>> think workqueues are more flexible and a better fit for this use case.
>>> Not only it is easy to schedule work in a workqueue from the interrupt
>>> handler, but also they can be used for sleeping in the request function
>>> if there is not enough room on the ring. Besides, they can easily be
>>> configured to share a single thread or to have multiple independent
>>> threads.
>>
>> I'm fine with the workqueues as long as you have decided to use them
>> considering the alternatives. :-)
>>
 Can't you use xenbus_read_unsigned() instead of xenbus_read()?
>>>
>>> I can use xenbus_read_unsigned in the other cases below, but not here,
>>> because versions is in the form: "1,3,4"
>>
>> Is this documented somewhere?
>>
>> Hmm, are any of the Xenstore entries documented? Shouldn't this be done
>> in xen_9pfs.h ?
>  
> They are documented in docs/misc/9pfs.markdown, under "Xenstore". Given
> that it's all written there, especially the semantics, I didn't repeat
> it in xen_9pfs.h

Looking at it from the Linux kernel perspective this documentation is
not really highly visible. For me it is okay, but there have been
multiple examples in the past where documentation in the Xen repository
wasn't regarded as being sufficient.

I recommend moving the documentation regarding the interface into the
header file like for the other pv interfaces.


Juergen



Re: change uprobe_events default ? Was: [PATCH] perf: Rename CONFIG_[UK]PROBE_EVENT to CONFIG_[UK]PROBE_EVENTS

2017-03-15 Thread Wangnan (F)



On 2017/3/16 9:06, Arnaldo Carvalho de Melo wrote:

Added more people to the CC list.

Em Wed, Mar 15, 2017 at 05:58:19PM -0700, Alexei Starovoitov escreveu:

On Thu, Feb 16, 2017 at 05:00:50PM +1100, Anton Blanchard wrote:

We have uses of CONFIG_UPROBE_EVENT and CONFIG_KPROBE_EVENT as
well as CONFIG_UPROBE_EVENTS and CONFIG_KPROBE_EVENTS. Consistently
use the plurals.
  

this rename made me notice that UPROBE_EVENTS still defaults to 'n'.
this is key feature that all distros enable, so having default 'n'
is kinda saying that it's not something that should be turned on
or used widely. which is obviously not the case.
imo it's time to change it to 'y'.
Thoughts?

Agreed, I also found it strange that it was disabled by default when I
recently did a 'make oldconfig' :-\

- Arnaldo


+1.

Some internal distros in my company now have started
discussing supporting user space probing. Turning
uprobes on for upstream kernel helps us saving a lot
of discussion.

Thank you.



Re: change uprobe_events default ? Was: [PATCH] perf: Rename CONFIG_[UK]PROBE_EVENT to CONFIG_[UK]PROBE_EVENTS

2017-03-15 Thread Wangnan (F)



On 2017/3/16 9:06, Arnaldo Carvalho de Melo wrote:

Added more people to the CC list.

Em Wed, Mar 15, 2017 at 05:58:19PM -0700, Alexei Starovoitov escreveu:

On Thu, Feb 16, 2017 at 05:00:50PM +1100, Anton Blanchard wrote:

We have uses of CONFIG_UPROBE_EVENT and CONFIG_KPROBE_EVENT as
well as CONFIG_UPROBE_EVENTS and CONFIG_KPROBE_EVENTS. Consistently
use the plurals.
  

this rename made me notice that UPROBE_EVENTS still defaults to 'n'.
this is key feature that all distros enable, so having default 'n'
is kinda saying that it's not something that should be turned on
or used widely. which is obviously not the case.
imo it's time to change it to 'y'.
Thoughts?

Agreed, I also found it strange that it was disabled by default when I
recently did a 'make oldconfig' :-\

- Arnaldo


+1.

Some internal distros in my company now have started
discussing supporting user space probing. Turning
uprobes on for upstream kernel helps us saving a lot
of discussion.

Thank you.



Re: [PATCH] ARM: dts: mvebu: linksys: enable buffer manager support

2017-03-15 Thread Ralph Sennhauser
On Wed, 15 Mar 2017 20:17:35 +0100
Gregory CLEMENT  wrote:

> Hi Ralph,
>  
>  On mer., mars 08 2017, Ralph Sennhauser 
> wrote:
> 
> 
>
> > @@ -88,6 +89,9 @@
> > ethernet@7 {
> > status = "okay";
> > phy-mode = "rgmii-id";
> > +   buffer-manager = <>;
> > +   bm,pool-long = <1>;
> > +   bm,pool-short = <3>;
> > fixed-link {
> > speed = <1000>;
> > full-duplex;
> > @@ -97,6 +101,9 @@
> > ethernet@34000 {
> > status = "okay";
> > phy-mode = "sgmii";
> > +   buffer-manager = <>;
> > +   bm,pool-long = <0>;
> > +   bm,pool-short = <3>;  
> Any reason to reuse the same pool than the other port?
> 
> As only two ports are used here, then each of them can have use 2 of
> the 4 availables pools. 
> 
> 

Hi Gregory,

It has been quite a while since I have written that patch. Something
written somewhere in the Documentation / commit message which I can't
find anymore gave me the impression that using the same for short
doesn't make a difference. So I went with the pool IDs used for other
similar boards for "consistency".

Will send a v2 shortly using all independent pools using the IDs witch
come most natural in context.

Thanks
Ralph


Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 11:50 AM, Michael Ellerman wrote:

Hi Peter,

Peter Zijlstra  writes:

On Tue, Mar 14, 2017 at 02:31:51PM +0530, Madhavan Srinivasan wrote:


Huh? PPC hasn't yet implemented this? Then why are you fixing it?

yes, PPC hasn't implemented this (until now).

until now where?

On powerpc there is currently no kernel support for filling the data_src
value with anything meaningful.

A user can still request PERF_SAMPLE_DATA_SRC (perf report -d), but they
just get the default value from perf_sample_data_init(), which is
PERF_MEM_NA.

Though even that is currently broken with a big endian perf tool.


And did not understand "Then why are you fixing it?"

I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?


Sorry, was out yesterday.

Yes my bad. I CCed lkml and ppcdev and took the emails
from get_maintainer script and added to each file.

I will send out a v3 with peterz and others in all patch.



Regardless of us wanting to do the kernel side on powerpc, the current
API is broken on big endian.

That's because in the kernel the PERF_MEM_NA value is constructed using
shifts:

   /* TLB access */
   #define PERF_MEM_TLB_NA  0x01 /* not available */
   ...
   #define PERF_MEM_TLB_SHIFT   26
   
   #define PERF_MEM_S(a, s) \

(((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
   
   #define PERF_MEM_NA (PERF_MEM_S(OP, NA)   |\

PERF_MEM_S(LVL, NA)   |\
PERF_MEM_S(SNOOP, NA) |\
PERF_MEM_S(LOCK, NA)  |\
PERF_MEM_S(TLB, NA))

Which works out as:

   ((0x01 << 0) | (0x01 << 5) | (0x01 << 19) | (0x01 << 24) | (0x01 << 26))


Which means the PERF_MEM_NA value comes out of the kernel as 0x5080021
in CPU endian.

But then in the perf tool, the code uses the bitfields to inspect the
value, and currently the bitfields are defined using little endian
ordering.

So eg. in perf_mem__tlb_scnprintf() we see:
   data_src->val = 0x5080021
  op = 0x0
 lvl = 0x0
   snoop = 0x0
lock = 0x0
dtlb = 0x0
rsvd = 0x5080021


So this patch does what I think is the minimal fix, of changing the
definition of the bitfields to match the values that are already
exported by the kernel on big endian. And it makes no change on little
endian.


Thanks for the detailed explanation. I will add this to the patch
commit message in the v3.

Maddy



cheers





Re: [PATCH] ARM: dts: mvebu: linksys: enable buffer manager support

2017-03-15 Thread Ralph Sennhauser
On Wed, 15 Mar 2017 20:17:35 +0100
Gregory CLEMENT  wrote:

> Hi Ralph,
>  
>  On mer., mars 08 2017, Ralph Sennhauser 
> wrote:
> 
> 
>
> > @@ -88,6 +89,9 @@
> > ethernet@7 {
> > status = "okay";
> > phy-mode = "rgmii-id";
> > +   buffer-manager = <>;
> > +   bm,pool-long = <1>;
> > +   bm,pool-short = <3>;
> > fixed-link {
> > speed = <1000>;
> > full-duplex;
> > @@ -97,6 +101,9 @@
> > ethernet@34000 {
> > status = "okay";
> > phy-mode = "sgmii";
> > +   buffer-manager = <>;
> > +   bm,pool-long = <0>;
> > +   bm,pool-short = <3>;  
> Any reason to reuse the same pool than the other port?
> 
> As only two ports are used here, then each of them can have use 2 of
> the 4 availables pools. 
> 
> 

Hi Gregory,

It has been quite a while since I have written that patch. Something
written somewhere in the Documentation / commit message which I can't
find anymore gave me the impression that using the same for short
doesn't make a difference. So I went with the pool IDs used for other
similar boards for "consistency".

Will send a v2 shortly using all independent pools using the IDs witch
come most natural in context.

Thanks
Ralph


Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 11:50 AM, Michael Ellerman wrote:

Hi Peter,

Peter Zijlstra  writes:

On Tue, Mar 14, 2017 at 02:31:51PM +0530, Madhavan Srinivasan wrote:


Huh? PPC hasn't yet implemented this? Then why are you fixing it?

yes, PPC hasn't implemented this (until now).

until now where?

On powerpc there is currently no kernel support for filling the data_src
value with anything meaningful.

A user can still request PERF_SAMPLE_DATA_SRC (perf report -d), but they
just get the default value from perf_sample_data_init(), which is
PERF_MEM_NA.

Though even that is currently broken with a big endian perf tool.


And did not understand "Then why are you fixing it?"

I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?


Sorry, was out yesterday.

Yes my bad. I CCed lkml and ppcdev and took the emails
from get_maintainer script and added to each file.

I will send out a v3 with peterz and others in all patch.



Regardless of us wanting to do the kernel side on powerpc, the current
API is broken on big endian.

That's because in the kernel the PERF_MEM_NA value is constructed using
shifts:

   /* TLB access */
   #define PERF_MEM_TLB_NA  0x01 /* not available */
   ...
   #define PERF_MEM_TLB_SHIFT   26
   
   #define PERF_MEM_S(a, s) \

(((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
   
   #define PERF_MEM_NA (PERF_MEM_S(OP, NA)   |\

PERF_MEM_S(LVL, NA)   |\
PERF_MEM_S(SNOOP, NA) |\
PERF_MEM_S(LOCK, NA)  |\
PERF_MEM_S(TLB, NA))

Which works out as:

   ((0x01 << 0) | (0x01 << 5) | (0x01 << 19) | (0x01 << 24) | (0x01 << 26))


Which means the PERF_MEM_NA value comes out of the kernel as 0x5080021
in CPU endian.

But then in the perf tool, the code uses the bitfields to inspect the
value, and currently the bitfields are defined using little endian
ordering.

So eg. in perf_mem__tlb_scnprintf() we see:
   data_src->val = 0x5080021
  op = 0x0
 lvl = 0x0
   snoop = 0x0
lock = 0x0
dtlb = 0x0
rsvd = 0x5080021


So this patch does what I think is the minimal fix, of changing the
definition of the bitfields to match the values that are already
exported by the kernel on big endian. And it makes no change on little
endian.


Thanks for the detailed explanation. I will add this to the patch
commit message in the v3.

Maddy



cheers





Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Sergey Senozhatsky
On (03/16/17 14:33), Minchan Kim wrote:
[..]
> "There is no user for it"
> 
> I was liar so need to be a honest guy.

ha-ha-ha. I didn't say that :)

[..]
> @@ -1414,7 +1414,7 @@ static bool try_to_unmap_one(struct page *page, struct 
> vm_area_struct *vma,
>*/
>   if (unlikely(PageSwapBacked(page) != 
> PageSwapCache(page))) {
>   WARN_ON_ONCE(1);
> - ret = SWAP_FAIL;
> + ret = false;
>   page_vma_mapped_walk_done();
>   break;
>   }


one thing to notice here is that 'ret = false' and 'ret = SWAP_FAIL'
are not the same and must produce different results. `ret' is bool
and SWAP_FAIL was 2. it's return 1 vs return 0, isn't it? so was
there a bug before?

-ss


Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Sergey Senozhatsky
On (03/16/17 14:33), Minchan Kim wrote:
[..]
> "There is no user for it"
> 
> I was liar so need to be a honest guy.

ha-ha-ha. I didn't say that :)

[..]
> @@ -1414,7 +1414,7 @@ static bool try_to_unmap_one(struct page *page, struct 
> vm_area_struct *vma,
>*/
>   if (unlikely(PageSwapBacked(page) != 
> PageSwapCache(page))) {
>   WARN_ON_ONCE(1);
> - ret = SWAP_FAIL;
> + ret = false;
>   page_vma_mapped_walk_done();
>   break;
>   }


one thing to notice here is that 'ret = false' and 'ret = SWAP_FAIL'
are not the same and must produce different results. `ret' is bool
and SWAP_FAIL was 2. it's return 1 vs return 0, isn't it? so was
there a bug before?

-ss


Re: perf: race with automatic rdpmc() disabling

2017-03-15 Thread Vince Weaver
On Wed, 15 Mar 2017, Andy Lutomirski wrote:

> Can you give this a try:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/commit/?h=x86/fixes=9edb8154863ba1a7f6f1f15ffe6aecf3cf32bf21
> 
> (The link doesn't work yet but it should in a minute or two.)

I've tested it and I am unable to reproduce the problem with the patch 
applied.

Vince


Re: perf: race with automatic rdpmc() disabling

2017-03-15 Thread Vince Weaver
On Wed, 15 Mar 2017, Andy Lutomirski wrote:

> Can you give this a try:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/commit/?h=x86/fixes=9edb8154863ba1a7f6f1f15ffe6aecf3cf32bf21
> 
> (The link doesn't work yet but it should in a minute or two.)

I've tested it and I am unable to reproduce the problem with the patch 
applied.

Vince


Re: [PATCH 2/2] usb; dwc3: of-simple: Add support to get resets for the device

2017-03-15 Thread Vivek Gautam

Hi,


On 03/15/2017 04:15 PM, Philipp Zabel wrote:

On Wed, 2017-02-22 at 10:54 +0530, Vivek Gautam wrote:

Add support to get a list of resets available for the device.
These resets must be kept de-asserted until the device is
in use.

Cc: Felipe Balbi 
Signed-off-by: Vivek Gautam 
---

Based on torvald's master branch.

  drivers/usb/dwc3/dwc3-of-simple.c | 49 +++
  1 file changed, 49 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
b/drivers/usb/dwc3/dwc3-of-simple.c
index fe414e7a9c78..025de7342d28 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -29,13 +29,52 @@
  #include 
  #include 
  #include 
+#include 
  
  struct dwc3_of_simple {

struct device   *dev;
struct clk  **clks;
int num_clocks;
+   struct reset_control**resets;
+   int num_resets;
  };
  
+static int dwc3_of_simple_reset_init(struct dwc3_of_simple *simple, int count)

+{
+   struct device   *dev = simple->dev;
+   int i;
+
+   simple->num_resets = count;
+
+   if (!count)
+   return 0;
+
+   simple->resets = devm_kcalloc(dev, simple->num_resets,
+   sizeof(struct reset_control *), GFP_KERNEL);
+   if (!simple->resets)
+   return -ENOMEM;
+
+   for (i = 0; i < simple->num_resets; i++) {
+   struct reset_control *reset;
+   int ret;
+
+   reset = devm_reset_control_get_by_index(dev, i);

Please use devm_reset_control_get_exclusive_by_index instead. See
include/linux/reset.h for details.


Sure, will make use of *exclusive version of the api.




+   if (IS_ERR(reset))
+   return PTR_ERR(reset);
+
+   simple->resets[i] = reset;
+
+   ret = reset_control_deassert(reset);
+   if (ret) {
+   while (--i >= 0)
+   reset_control_assert(reset);
+   return ret;
+   }
+   }
+
+   return 0;
+}

This looks rather generic. Should we have a
reset_control_get/assert/deassert_array functionality at the reset API
level?


Yes, i think we should. Something on the lines of 'regulator_bulk_*' 
interface?





  static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
  {
struct device   *dev = simple->dev;
@@ -100,6 +139,10 @@ static int dwc3_of_simple_probe(struct platform_device 
*pdev)
if (ret)
return ret;
  
+	ret = dwc3_of_simple_reset_init(simple, of_reset_control_get_count(np));

+   if (ret)
+   return ret;
+

Not a blocker, but it seems a bit inconsistent to count the reset
controls via the device node (of_...), but then get them via the device
(devm_reset_control_get_... instead of of_reset_control_get_...).


You are right, it looks inconsistent. I thought of using a resource
managed API. But now i think it doesn't make much sense.


Best Regards
Vivek



regards
Philipp



--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH 2/2] usb; dwc3: of-simple: Add support to get resets for the device

2017-03-15 Thread Vivek Gautam

Hi,


On 03/15/2017 04:15 PM, Philipp Zabel wrote:

On Wed, 2017-02-22 at 10:54 +0530, Vivek Gautam wrote:

Add support to get a list of resets available for the device.
These resets must be kept de-asserted until the device is
in use.

Cc: Felipe Balbi 
Signed-off-by: Vivek Gautam 
---

Based on torvald's master branch.

  drivers/usb/dwc3/dwc3-of-simple.c | 49 +++
  1 file changed, 49 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
b/drivers/usb/dwc3/dwc3-of-simple.c
index fe414e7a9c78..025de7342d28 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -29,13 +29,52 @@
  #include 
  #include 
  #include 
+#include 
  
  struct dwc3_of_simple {

struct device   *dev;
struct clk  **clks;
int num_clocks;
+   struct reset_control**resets;
+   int num_resets;
  };
  
+static int dwc3_of_simple_reset_init(struct dwc3_of_simple *simple, int count)

+{
+   struct device   *dev = simple->dev;
+   int i;
+
+   simple->num_resets = count;
+
+   if (!count)
+   return 0;
+
+   simple->resets = devm_kcalloc(dev, simple->num_resets,
+   sizeof(struct reset_control *), GFP_KERNEL);
+   if (!simple->resets)
+   return -ENOMEM;
+
+   for (i = 0; i < simple->num_resets; i++) {
+   struct reset_control *reset;
+   int ret;
+
+   reset = devm_reset_control_get_by_index(dev, i);

Please use devm_reset_control_get_exclusive_by_index instead. See
include/linux/reset.h for details.


Sure, will make use of *exclusive version of the api.




+   if (IS_ERR(reset))
+   return PTR_ERR(reset);
+
+   simple->resets[i] = reset;
+
+   ret = reset_control_deassert(reset);
+   if (ret) {
+   while (--i >= 0)
+   reset_control_assert(reset);
+   return ret;
+   }
+   }
+
+   return 0;
+}

This looks rather generic. Should we have a
reset_control_get/assert/deassert_array functionality at the reset API
level?


Yes, i think we should. Something on the lines of 'regulator_bulk_*' 
interface?





  static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
  {
struct device   *dev = simple->dev;
@@ -100,6 +139,10 @@ static int dwc3_of_simple_probe(struct platform_device 
*pdev)
if (ret)
return ret;
  
+	ret = dwc3_of_simple_reset_init(simple, of_reset_control_get_count(np));

+   if (ret)
+   return ret;
+

Not a blocker, but it seems a bit inconsistent to count the reset
controls via the device node (of_...), but then get them via the device
(devm_reset_control_get_... instead of of_reset_control_get_...).


You are right, it looks inconsistent. I thought of using a resource
managed API. But now i think it doesn't make much sense.


Best Regards
Vivek



regards
Philipp



--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: change uprobe_events default ? Was: [PATCH] perf: Rename CONFIG_[UK]PROBE_EVENT to CONFIG_[UK]PROBE_EVENTS

2017-03-15 Thread Srikar Dronamraju
> Added more people to the CC list.
> 
> Em Wed, Mar 15, 2017 at 05:58:19PM -0700, Alexei Starovoitov escreveu:
> > On Thu, Feb 16, 2017 at 05:00:50PM +1100, Anton Blanchard wrote:
> > > We have uses of CONFIG_UPROBE_EVENT and CONFIG_KPROBE_EVENT as
> > > well as CONFIG_UPROBE_EVENTS and CONFIG_KPROBE_EVENTS. Consistently
> > > use the plurals.
> 
> > this rename made me notice that UPROBE_EVENTS still defaults to 'n'.
> > this is key feature that all distros enable, so having default 'n'
> > is kinda saying that it's not something that should be turned on
> > or used widely. which is obviously not the case.
> > imo it's time to change it to 'y'.
> > Thoughts?
> 
> Agreed, I also found it strange that it was disabled by default when I
> recently did a 'make oldconfig' :-\

Yes, we could make it default on.



Re: change uprobe_events default ? Was: [PATCH] perf: Rename CONFIG_[UK]PROBE_EVENT to CONFIG_[UK]PROBE_EVENTS

2017-03-15 Thread Srikar Dronamraju
> Added more people to the CC list.
> 
> Em Wed, Mar 15, 2017 at 05:58:19PM -0700, Alexei Starovoitov escreveu:
> > On Thu, Feb 16, 2017 at 05:00:50PM +1100, Anton Blanchard wrote:
> > > We have uses of CONFIG_UPROBE_EVENT and CONFIG_KPROBE_EVENT as
> > > well as CONFIG_UPROBE_EVENTS and CONFIG_KPROBE_EVENTS. Consistently
> > > use the plurals.
> 
> > this rename made me notice that UPROBE_EVENTS still defaults to 'n'.
> > this is key feature that all distros enable, so having default 'n'
> > is kinda saying that it's not something that should be turned on
> > or used widely. which is obviously not the case.
> > imo it's time to change it to 'y'.
> > Thoughts?
> 
> Agreed, I also found it strange that it was disabled by default when I
> recently did a 'make oldconfig' :-\

Yes, we could make it default on.



[PATCH 03/17] thermal: cpu_cooling: Replace cpufreq_device with cpufreq_dev

2017-03-15 Thread Viresh Kumar
Objects of "struct cpufreq_cooling_device" are named a bit
inconsistently. Lets use cpufreq_dev everywhere.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 133 +-
 1 file changed, 66 insertions(+), 67 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7ce73eee866f..7a19033d7f79 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -218,11 +218,11 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 
 /**
  * build_dyn_power_table() - create a dynamic power to frequency table
- * @cpufreq_device:the cpufreq cooling device in which to store the table
+ * @cpufreq_dev:   the cpufreq cooling device in which to store the table
  * @capacitance: dynamic power coefficient for these cpus
  *
  * Build a dynamic power to frequency table for this cpu and store it
- * in @cpufreq_device.  This table will be used in cpu_power_to_freq() and
+ * in @cpufreq_dev.  This table will be used in cpu_power_to_freq() and
  * cpu_freq_to_power() to convert between power and frequency
  * efficiently.  Power is stored in mW, frequency in KHz.  The
  * resulting table is in ascending order.
@@ -231,7 +231,7 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
  * -ENOMEM if we run out of memory or -EAGAIN if an OPP was
  * added/enabled while the function was executing.
  */
-static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
+static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_dev,
 u32 capacitance)
 {
struct power_table *power_table;
@@ -240,10 +240,10 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_device,
int num_opps = 0, cpu, i, ret = 0;
unsigned long freq;
 
-   for_each_cpu(cpu, _device->allowed_cpus) {
+   for_each_cpu(cpu, _dev->allowed_cpus) {
dev = get_cpu_device(cpu);
if (!dev) {
-   dev_warn(_device->cool_dev->device,
+   dev_warn(_dev->cool_dev->device,
 "No cpu device for cpu %d\n", cpu);
continue;
}
@@ -296,9 +296,9 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_device,
goto free_power_table;
}
 
-   cpufreq_device->cpu_dev = dev;
-   cpufreq_device->dyn_power_table = power_table;
-   cpufreq_device->dyn_power_table_entries = i;
+   cpufreq_dev->cpu_dev = dev;
+   cpufreq_dev->dyn_power_table = power_table;
+   cpufreq_dev->dyn_power_table_entries = i;
 
return 0;
 
@@ -308,26 +308,26 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_device,
return ret;
 }
 
-static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_device,
+static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_dev,
 u32 freq)
 {
int i;
-   struct power_table *pt = cpufreq_device->dyn_power_table;
+   struct power_table *pt = cpufreq_dev->dyn_power_table;
 
-   for (i = 1; i < cpufreq_device->dyn_power_table_entries; i++)
+   for (i = 1; i < cpufreq_dev->dyn_power_table_entries; i++)
if (freq < pt[i].frequency)
break;
 
return pt[i - 1].power;
 }
 
-static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device,
+static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_dev,
 u32 power)
 {
int i;
-   struct power_table *pt = cpufreq_device->dyn_power_table;
+   struct power_table *pt = cpufreq_dev->dyn_power_table;
 
-   for (i = 1; i < cpufreq_device->dyn_power_table_entries; i++)
+   for (i = 1; i < cpufreq_dev->dyn_power_table_entries; i++)
if (power < pt[i].power)
break;
 
@@ -336,37 +336,37 @@ static u32 cpu_power_to_freq(struct 
cpufreq_cooling_device *cpufreq_device,
 
 /**
  * get_load() - get load for a cpu since last updated
- * @cpufreq_device: cpufreq_cooling_device for this cpu
+ * @cpufreq_dev:cpufreq_cooling_device for this cpu
  * @cpu:   cpu number
- * @cpu_idx:   index of the cpu in cpufreq_device->allowed_cpus
+ * @cpu_idx:   index of the cpu in cpufreq_dev->allowed_cpus
  *
  * Return: The average load of cpu @cpu in percentage since this
  * function was last called.
  */
-static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu,
+static u32 get_load(struct cpufreq_cooling_device *cpufreq_dev, int cpu,
int cpu_idx)
 {
u32 load;
u64 now, now_idle, delta_time, delta_idle;
 
now_idle = get_cpu_idle_time(cpu, , 0);
-   delta_idle = now_idle - cpufreq_device->time_in_idle[cpu_idx];
-   delta_time = now - 

[PATCH 03/17] thermal: cpu_cooling: Replace cpufreq_device with cpufreq_dev

2017-03-15 Thread Viresh Kumar
Objects of "struct cpufreq_cooling_device" are named a bit
inconsistently. Lets use cpufreq_dev everywhere.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 133 +-
 1 file changed, 66 insertions(+), 67 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7ce73eee866f..7a19033d7f79 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -218,11 +218,11 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 
 /**
  * build_dyn_power_table() - create a dynamic power to frequency table
- * @cpufreq_device:the cpufreq cooling device in which to store the table
+ * @cpufreq_dev:   the cpufreq cooling device in which to store the table
  * @capacitance: dynamic power coefficient for these cpus
  *
  * Build a dynamic power to frequency table for this cpu and store it
- * in @cpufreq_device.  This table will be used in cpu_power_to_freq() and
+ * in @cpufreq_dev.  This table will be used in cpu_power_to_freq() and
  * cpu_freq_to_power() to convert between power and frequency
  * efficiently.  Power is stored in mW, frequency in KHz.  The
  * resulting table is in ascending order.
@@ -231,7 +231,7 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
  * -ENOMEM if we run out of memory or -EAGAIN if an OPP was
  * added/enabled while the function was executing.
  */
-static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
+static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_dev,
 u32 capacitance)
 {
struct power_table *power_table;
@@ -240,10 +240,10 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_device,
int num_opps = 0, cpu, i, ret = 0;
unsigned long freq;
 
-   for_each_cpu(cpu, _device->allowed_cpus) {
+   for_each_cpu(cpu, _dev->allowed_cpus) {
dev = get_cpu_device(cpu);
if (!dev) {
-   dev_warn(_device->cool_dev->device,
+   dev_warn(_dev->cool_dev->device,
 "No cpu device for cpu %d\n", cpu);
continue;
}
@@ -296,9 +296,9 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_device,
goto free_power_table;
}
 
-   cpufreq_device->cpu_dev = dev;
-   cpufreq_device->dyn_power_table = power_table;
-   cpufreq_device->dyn_power_table_entries = i;
+   cpufreq_dev->cpu_dev = dev;
+   cpufreq_dev->dyn_power_table = power_table;
+   cpufreq_dev->dyn_power_table_entries = i;
 
return 0;
 
@@ -308,26 +308,26 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_device,
return ret;
 }
 
-static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_device,
+static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_dev,
 u32 freq)
 {
int i;
-   struct power_table *pt = cpufreq_device->dyn_power_table;
+   struct power_table *pt = cpufreq_dev->dyn_power_table;
 
-   for (i = 1; i < cpufreq_device->dyn_power_table_entries; i++)
+   for (i = 1; i < cpufreq_dev->dyn_power_table_entries; i++)
if (freq < pt[i].frequency)
break;
 
return pt[i - 1].power;
 }
 
-static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device,
+static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_dev,
 u32 power)
 {
int i;
-   struct power_table *pt = cpufreq_device->dyn_power_table;
+   struct power_table *pt = cpufreq_dev->dyn_power_table;
 
-   for (i = 1; i < cpufreq_device->dyn_power_table_entries; i++)
+   for (i = 1; i < cpufreq_dev->dyn_power_table_entries; i++)
if (power < pt[i].power)
break;
 
@@ -336,37 +336,37 @@ static u32 cpu_power_to_freq(struct 
cpufreq_cooling_device *cpufreq_device,
 
 /**
  * get_load() - get load for a cpu since last updated
- * @cpufreq_device: cpufreq_cooling_device for this cpu
+ * @cpufreq_dev:cpufreq_cooling_device for this cpu
  * @cpu:   cpu number
- * @cpu_idx:   index of the cpu in cpufreq_device->allowed_cpus
+ * @cpu_idx:   index of the cpu in cpufreq_dev->allowed_cpus
  *
  * Return: The average load of cpu @cpu in percentage since this
  * function was last called.
  */
-static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu,
+static u32 get_load(struct cpufreq_cooling_device *cpufreq_dev, int cpu,
int cpu_idx)
 {
u32 load;
u64 now, now_idle, delta_time, delta_idle;
 
now_idle = get_cpu_idle_time(cpu, , 0);
-   delta_idle = now_idle - cpufreq_device->time_in_idle[cpu_idx];
-   delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu_idx];

[PATCH 10/17] thermal: cpu_cooling: OPPs are registered for all CPUs

2017-03-15 Thread Viresh Kumar
The OPPs are registered for all CPUs of a cpufreq policy now and we
don't need to run the loop in build_dyn_power_table(). Just check for
the policy->cpu and we should be fine.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7590279bf1de..1df6c9039e45 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -83,7 +83,7 @@ struct power_table {
  * @dyn_power_table: array of struct power_table for frequency to power
  * conversion, sorted in ascending order.
  * @dyn_power_table_entries: number of entries in the @dyn_power_table array
- * @cpu_dev: the first cpu_device from @allowed_cpus that has OPPs registered
+ * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
  * This structure is required for keeping information of each registered
@@ -208,24 +208,20 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_dev,
struct power_table *power_table;
struct dev_pm_opp *opp;
struct device *dev = NULL;
-   int num_opps = 0, cpu, i, ret = 0;
+   int num_opps = 0, cpu = cpufreq_dev->policy->cpu, i, ret = 0;
unsigned long freq;
 
-   for_each_cpu(cpu, _dev->allowed_cpus) {
-   dev = get_cpu_device(cpu);
-   if (!dev) {
-   dev_warn(_dev->cdev->device,
-"No cpu device for cpu %d\n", cpu);
-   continue;
-   }
-
-   num_opps = dev_pm_opp_get_opp_count(dev);
-   if (num_opps > 0)
-   break;
-   else if (num_opps < 0)
-   return num_opps;
+   dev = get_cpu_device(cpu);
+   if (unlikely(!dev)) {
+   dev_warn(_dev->cdev->device,
+"No cpu device for cpu %d\n", cpu);
+   return -ENODEV;
}
 
+   num_opps = dev_pm_opp_get_opp_count(dev);
+   if (num_opps < 0)
+   return num_opps;
+
if (num_opps == 0)
return -EINVAL;
 
-- 
2.7.1.410.g6faf27b



[PATCH 07/17] thermal: cpu_cooling: use cpufreq_policy to register cooling device

2017-03-15 Thread Viresh Kumar
The CPU cooling driver uses the cpufreq policy, to get clip_cpus, the
frequency table, etc. Most of the callers of CPU cooling driver's
registration routines have the cpufreq policy with them, but they only
pass the policy->related_cpus cpumask. The __cpufreq_cooling_register()
routine then gets the policy by itself and uses it.

It would be much better if the callers can pass the policy instead
directly. This also fixes a basic design flaw, where the policy can be
freed while the CPU cooling driver is still active.

Signed-off-by: Viresh Kumar 
---
 drivers/cpufreq/arm_big_little.c   |  2 +-
 drivers/cpufreq/cpufreq-dt.c   |  2 +-
 drivers/cpufreq/dbx500-cpufreq.c   |  2 +-
 drivers/cpufreq/mt8173-cpufreq.c   |  4 +-
 drivers/cpufreq/qoriq-cpufreq.c|  3 +-
 drivers/thermal/cpu_cooling.c  | 60 --
 drivers/thermal/imx_thermal.c  | 22 ++--
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 22 +---
 include/linux/cpu_cooling.h| 26 +-
 9 files changed, 71 insertions(+), 72 deletions(-)

diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 418042201e6d..ea6d62547b10 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -540,7 +540,7 @@ static void bL_cpufreq_ready(struct cpufreq_policy *policy)
 _coefficient);
 
cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
-   policy->related_cpus, power_coefficient, NULL);
+   policy, power_coefficient, NULL);
if (IS_ERR(cdev[cur_cluster])) {
dev_err(cpu_dev,
"running cpufreq without cooling device: %ld\n",
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index c943787d761e..fef3c2160691 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -326,7 +326,7 @@ static void cpufreq_ready(struct cpufreq_policy *policy)
 _coefficient);
 
priv->cdev = of_cpufreq_power_cooling_register(np,
-   policy->related_cpus, power_coefficient, NULL);
+   policy, power_coefficient, NULL);
if (IS_ERR(priv->cdev)) {
dev_err(priv->cpu_dev,
"running cpufreq without cooling device: %ld\n",
diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c
index 3575b82210ba..4ee0431579c1 100644
--- a/drivers/cpufreq/dbx500-cpufreq.c
+++ b/drivers/cpufreq/dbx500-cpufreq.c
@@ -43,7 +43,7 @@ static int dbx500_cpufreq_exit(struct cpufreq_policy *policy)
 
 static void dbx500_cpufreq_ready(struct cpufreq_policy *policy)
 {
-   cdev = cpufreq_cooling_register(policy->cpus);
+   cdev = cpufreq_cooling_register(policy);
if (IS_ERR(cdev))
pr_err("Failed to register cooling device %ld\n", 
PTR_ERR(cdev));
else
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
index fd1886faf33a..f9f00fb4bc3a 100644
--- a/drivers/cpufreq/mt8173-cpufreq.c
+++ b/drivers/cpufreq/mt8173-cpufreq.c
@@ -320,9 +320,7 @@ static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
of_property_read_u32(np, DYNAMIC_POWER, );
 
info->cdev = of_cpufreq_power_cooling_register(np,
-   policy->related_cpus,
-   capacitance,
-   NULL);
+   policy, capacitance, NULL);
 
if (IS_ERR(info->cdev)) {
dev_err(info->cpu_dev,
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index e2ea433a5f9c..4ada55b8856e 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -278,8 +278,7 @@ static void qoriq_cpufreq_ready(struct cpufreq_policy 
*policy)
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
 
if (of_find_property(np, "#cooling-cells", NULL)) {
-   cpud->cdev = of_cpufreq_cooling_register(np,
-policy->related_cpus);
+   cpud->cdev = of_cpufreq_cooling_register(np, policy);
 
if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) {
pr_err("cpu%d is not running as cooling device: %ld\n",
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 46e90122b746..a97ebb7bf27f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -718,7 +718,7 @@ static unsigned int find_next_max(struct 

[PATCH 07/17] thermal: cpu_cooling: use cpufreq_policy to register cooling device

2017-03-15 Thread Viresh Kumar
The CPU cooling driver uses the cpufreq policy, to get clip_cpus, the
frequency table, etc. Most of the callers of CPU cooling driver's
registration routines have the cpufreq policy with them, but they only
pass the policy->related_cpus cpumask. The __cpufreq_cooling_register()
routine then gets the policy by itself and uses it.

It would be much better if the callers can pass the policy instead
directly. This also fixes a basic design flaw, where the policy can be
freed while the CPU cooling driver is still active.

Signed-off-by: Viresh Kumar 
---
 drivers/cpufreq/arm_big_little.c   |  2 +-
 drivers/cpufreq/cpufreq-dt.c   |  2 +-
 drivers/cpufreq/dbx500-cpufreq.c   |  2 +-
 drivers/cpufreq/mt8173-cpufreq.c   |  4 +-
 drivers/cpufreq/qoriq-cpufreq.c|  3 +-
 drivers/thermal/cpu_cooling.c  | 60 --
 drivers/thermal/imx_thermal.c  | 22 ++--
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 22 +---
 include/linux/cpu_cooling.h| 26 +-
 9 files changed, 71 insertions(+), 72 deletions(-)

diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 418042201e6d..ea6d62547b10 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -540,7 +540,7 @@ static void bL_cpufreq_ready(struct cpufreq_policy *policy)
 _coefficient);
 
cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
-   policy->related_cpus, power_coefficient, NULL);
+   policy, power_coefficient, NULL);
if (IS_ERR(cdev[cur_cluster])) {
dev_err(cpu_dev,
"running cpufreq without cooling device: %ld\n",
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index c943787d761e..fef3c2160691 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -326,7 +326,7 @@ static void cpufreq_ready(struct cpufreq_policy *policy)
 _coefficient);
 
priv->cdev = of_cpufreq_power_cooling_register(np,
-   policy->related_cpus, power_coefficient, NULL);
+   policy, power_coefficient, NULL);
if (IS_ERR(priv->cdev)) {
dev_err(priv->cpu_dev,
"running cpufreq without cooling device: %ld\n",
diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c
index 3575b82210ba..4ee0431579c1 100644
--- a/drivers/cpufreq/dbx500-cpufreq.c
+++ b/drivers/cpufreq/dbx500-cpufreq.c
@@ -43,7 +43,7 @@ static int dbx500_cpufreq_exit(struct cpufreq_policy *policy)
 
 static void dbx500_cpufreq_ready(struct cpufreq_policy *policy)
 {
-   cdev = cpufreq_cooling_register(policy->cpus);
+   cdev = cpufreq_cooling_register(policy);
if (IS_ERR(cdev))
pr_err("Failed to register cooling device %ld\n", 
PTR_ERR(cdev));
else
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
index fd1886faf33a..f9f00fb4bc3a 100644
--- a/drivers/cpufreq/mt8173-cpufreq.c
+++ b/drivers/cpufreq/mt8173-cpufreq.c
@@ -320,9 +320,7 @@ static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
of_property_read_u32(np, DYNAMIC_POWER, );
 
info->cdev = of_cpufreq_power_cooling_register(np,
-   policy->related_cpus,
-   capacitance,
-   NULL);
+   policy, capacitance, NULL);
 
if (IS_ERR(info->cdev)) {
dev_err(info->cpu_dev,
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index e2ea433a5f9c..4ada55b8856e 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -278,8 +278,7 @@ static void qoriq_cpufreq_ready(struct cpufreq_policy 
*policy)
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
 
if (of_find_property(np, "#cooling-cells", NULL)) {
-   cpud->cdev = of_cpufreq_cooling_register(np,
-policy->related_cpus);
+   cpud->cdev = of_cpufreq_cooling_register(np, policy);
 
if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) {
pr_err("cpu%d is not running as cooling device: %ld\n",
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 46e90122b746..a97ebb7bf27f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -718,7 +718,7 @@ static unsigned int find_next_max(struct 
cpufreq_frequency_table 

[PATCH 10/17] thermal: cpu_cooling: OPPs are registered for all CPUs

2017-03-15 Thread Viresh Kumar
The OPPs are registered for all CPUs of a cpufreq policy now and we
don't need to run the loop in build_dyn_power_table(). Just check for
the policy->cpu and we should be fine.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7590279bf1de..1df6c9039e45 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -83,7 +83,7 @@ struct power_table {
  * @dyn_power_table: array of struct power_table for frequency to power
  * conversion, sorted in ascending order.
  * @dyn_power_table_entries: number of entries in the @dyn_power_table array
- * @cpu_dev: the first cpu_device from @allowed_cpus that has OPPs registered
+ * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
  * This structure is required for keeping information of each registered
@@ -208,24 +208,20 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_dev,
struct power_table *power_table;
struct dev_pm_opp *opp;
struct device *dev = NULL;
-   int num_opps = 0, cpu, i, ret = 0;
+   int num_opps = 0, cpu = cpufreq_dev->policy->cpu, i, ret = 0;
unsigned long freq;
 
-   for_each_cpu(cpu, _dev->allowed_cpus) {
-   dev = get_cpu_device(cpu);
-   if (!dev) {
-   dev_warn(_dev->cdev->device,
-"No cpu device for cpu %d\n", cpu);
-   continue;
-   }
-
-   num_opps = dev_pm_opp_get_opp_count(dev);
-   if (num_opps > 0)
-   break;
-   else if (num_opps < 0)
-   return num_opps;
+   dev = get_cpu_device(cpu);
+   if (unlikely(!dev)) {
+   dev_warn(_dev->cdev->device,
+"No cpu device for cpu %d\n", cpu);
+   return -ENODEV;
}
 
+   num_opps = dev_pm_opp_get_opp_count(dev);
+   if (num_opps < 0)
+   return num_opps;
+
if (num_opps == 0)
return -EINVAL;
 
-- 
2.7.1.410.g6faf27b



Re: ZONE_NORMAL vs. ZONE_MOVABLE

2017-03-15 Thread Joonsoo Kim
On Wed, Mar 15, 2017 at 05:37:29PM +0100, Andrea Arcangeli wrote:
> On Wed, Mar 15, 2017 at 02:11:40PM +0100, Michal Hocko wrote:
> > OK, I see now. I am afraid there is quite a lot of code which expects
> > that zones do not overlap. We can have holes in zones but not different
> > zones interleaving. Probably something which could be addressed but far
> > from trivial IMHO.
> > 
> > All that being said, I do not want to discourage you from experiments in
> > those areas. Just be prepared all those are far from trivial and
> > something for a long project ;)
> 
> This constraint was known for quite some time, so when I talked about
> this very constraint with Mel at least year LSF/MM he suggested sticky
> pageblocks would be superior to the current movable zone.
> 
> So instead of having a Movable zone, we could use the pageblocks but
> make it sticky-movable so they're only going to accept __GFP_MOVABLE
> allocations into them. It would be still a quite large change indeed
> but it looks simpler and with fewer drawbacks than trying to make the
> zone overlap.

Hello,

I don't follow up previous discussion so please let me know if I miss
something. I'd just like to mention about sticky pageblocks.

Before that, I'd like to say that a lot of code already deals with zone
overlap. Zone overlap exists for a long time although I don't know exact
history. IIRC, Mel fixed such a case before and compaction code has a
check for it. And, I added the overlap check to some pfn iterators which
doesn't have such a check for preparation of introducing a new zone,
ZONE_CMA, which has zone range overlap property. See following commits.

'ba6b097', '9d43f5a', 'a91c43c'.

Come to my main topic, I disagree that sticky pageblock would be
superior to the current separate zone approach. There is some reasons
about the objection to sticky movable pageblock in following link.

Sticky movable pageblock is conceptually same with MIGRATE_CMA and it
will cause many subtle issues like as MIGRATE_CMA did for CMA users.
MIGRATE_CMA introduces many hooks in various code path, and, to fix the
remaining issues, it needs more hooks. I don't think it is
maintainable approach. If you see following link which implements ZONE
approach, you can see that many hooks are removed in the end.

lkml.kernel.org/r/1476414196-3514-1-git-send-email-iamjoonsoo@lge.com

I don't know exact requirement on memory hotplug so it would be
possible that ZONE approach is not suitable for it. But, anyway, sticky
pageblock seems not to be a good solution to me.

Thanks.



Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Minchan Kim
Hey, Sergey,

On Thu, Mar 16, 2017 at 01:40:23PM +0900, Sergey Senozhatsky wrote:
> Hello,
> 
> 
> On (03/15/17 14:24), Minchan Kim wrote:
> > There is no user for it. Remove it.
> > 
> 
> there is one.
> 
> mm/rmap.c
> 
> try_to_unmap_one()
> ...
>   if (unlikely(PageSwapBacked(page) != PageSwapCache(page))) {
>   WARN_ON_ONCE(1);
>   ret = SWAP_FAIL;
>   page_vma_mapped_walk_done();
>   break;
>   }

"There is no user for it"

I was liar so need to be a honest guy.
Thanks, Sergey!

Andrew, Please make me honest. Sorry about that.

>From 286eae763d145338dc6c437258a741f293fab609 Mon Sep 17 00:00:00 2001
From: Minchan Kim 
Date: Thu, 16 Mar 2017 14:20:42 +0900
Subject: [PATCH] mm: use false instead of SWAP_FAIL

There was mistake with git-rebase.
SWAP_FAIL was removed. Use false.
It could be folded into mm-make-ttus-return-boolean.patch.

Reported-by: Sergey Senozhatsky 
Signed-off-by: Minchan Kim 
---
 mm/rmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index aa25fde..2422758 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1414,7 +1414,7 @@ static bool try_to_unmap_one(struct page *page, struct 
vm_area_struct *vma,
 */
if (unlikely(PageSwapBacked(page) != 
PageSwapCache(page))) {
WARN_ON_ONCE(1);
-   ret = SWAP_FAIL;
+   ret = false;
page_vma_mapped_walk_done();
break;
}
-- 
2.7.4



Re: ZONE_NORMAL vs. ZONE_MOVABLE

2017-03-15 Thread Joonsoo Kim
On Wed, Mar 15, 2017 at 05:37:29PM +0100, Andrea Arcangeli wrote:
> On Wed, Mar 15, 2017 at 02:11:40PM +0100, Michal Hocko wrote:
> > OK, I see now. I am afraid there is quite a lot of code which expects
> > that zones do not overlap. We can have holes in zones but not different
> > zones interleaving. Probably something which could be addressed but far
> > from trivial IMHO.
> > 
> > All that being said, I do not want to discourage you from experiments in
> > those areas. Just be prepared all those are far from trivial and
> > something for a long project ;)
> 
> This constraint was known for quite some time, so when I talked about
> this very constraint with Mel at least year LSF/MM he suggested sticky
> pageblocks would be superior to the current movable zone.
> 
> So instead of having a Movable zone, we could use the pageblocks but
> make it sticky-movable so they're only going to accept __GFP_MOVABLE
> allocations into them. It would be still a quite large change indeed
> but it looks simpler and with fewer drawbacks than trying to make the
> zone overlap.

Hello,

I don't follow up previous discussion so please let me know if I miss
something. I'd just like to mention about sticky pageblocks.

Before that, I'd like to say that a lot of code already deals with zone
overlap. Zone overlap exists for a long time although I don't know exact
history. IIRC, Mel fixed such a case before and compaction code has a
check for it. And, I added the overlap check to some pfn iterators which
doesn't have such a check for preparation of introducing a new zone,
ZONE_CMA, which has zone range overlap property. See following commits.

'ba6b097', '9d43f5a', 'a91c43c'.

Come to my main topic, I disagree that sticky pageblock would be
superior to the current separate zone approach. There is some reasons
about the objection to sticky movable pageblock in following link.

Sticky movable pageblock is conceptually same with MIGRATE_CMA and it
will cause many subtle issues like as MIGRATE_CMA did for CMA users.
MIGRATE_CMA introduces many hooks in various code path, and, to fix the
remaining issues, it needs more hooks. I don't think it is
maintainable approach. If you see following link which implements ZONE
approach, you can see that many hooks are removed in the end.

lkml.kernel.org/r/1476414196-3514-1-git-send-email-iamjoonsoo@lge.com

I don't know exact requirement on memory hotplug so it would be
possible that ZONE approach is not suitable for it. But, anyway, sticky
pageblock seems not to be a good solution to me.

Thanks.



Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Minchan Kim
Hey, Sergey,

On Thu, Mar 16, 2017 at 01:40:23PM +0900, Sergey Senozhatsky wrote:
> Hello,
> 
> 
> On (03/15/17 14:24), Minchan Kim wrote:
> > There is no user for it. Remove it.
> > 
> 
> there is one.
> 
> mm/rmap.c
> 
> try_to_unmap_one()
> ...
>   if (unlikely(PageSwapBacked(page) != PageSwapCache(page))) {
>   WARN_ON_ONCE(1);
>   ret = SWAP_FAIL;
>   page_vma_mapped_walk_done();
>   break;
>   }

"There is no user for it"

I was liar so need to be a honest guy.
Thanks, Sergey!

Andrew, Please make me honest. Sorry about that.

>From 286eae763d145338dc6c437258a741f293fab609 Mon Sep 17 00:00:00 2001
From: Minchan Kim 
Date: Thu, 16 Mar 2017 14:20:42 +0900
Subject: [PATCH] mm: use false instead of SWAP_FAIL

There was mistake with git-rebase.
SWAP_FAIL was removed. Use false.
It could be folded into mm-make-ttus-return-boolean.patch.

Reported-by: Sergey Senozhatsky 
Signed-off-by: Minchan Kim 
---
 mm/rmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index aa25fde..2422758 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1414,7 +1414,7 @@ static bool try_to_unmap_one(struct page *page, struct 
vm_area_struct *vma,
 */
if (unlikely(PageSwapBacked(page) != 
PageSwapCache(page))) {
WARN_ON_ONCE(1);
-   ret = SWAP_FAIL;
+   ret = false;
page_vma_mapped_walk_done();
break;
}
-- 
2.7.4



[PATCH 08/17] cpufreq: create cpufreq_table_count_valid_entries()

2017-03-15 Thread Viresh Kumar
We need such a routine at two places already, lets create one.

Signed-off-by: Viresh Kumar 
---
 drivers/cpufreq/cpufreq_stats.c | 13 -
 drivers/thermal/cpu_cooling.c   | 22 +-
 include/linux/cpufreq.h | 14 ++
 3 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index f570ead62454..9c3d319dc129 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -170,11 +170,10 @@ void cpufreq_stats_create_table(struct cpufreq_policy 
*policy)
unsigned int i = 0, count = 0, ret = -ENOMEM;
struct cpufreq_stats *stats;
unsigned int alloc_size;
-   struct cpufreq_frequency_table *pos, *table;
+   struct cpufreq_frequency_table *pos;
 
-   /* We need cpufreq table for creating stats table */
-   table = policy->freq_table;
-   if (unlikely(!table))
+   count = cpufreq_table_count_valid_entries(policy);
+   if (!count)
return;
 
/* stats already initialized */
@@ -185,10 +184,6 @@ void cpufreq_stats_create_table(struct cpufreq_policy 
*policy)
if (!stats)
return;
 
-   /* Find total allocation size */
-   cpufreq_for_each_valid_entry(pos, table)
-   count++;
-
alloc_size = count * sizeof(int) + count * sizeof(u64);
 
alloc_size += count * count * sizeof(int);
@@ -205,7 +200,7 @@ void cpufreq_stats_create_table(struct cpufreq_policy 
*policy)
stats->max_state = count;
 
/* Find valid-unique entries */
-   cpufreq_for_each_valid_entry(pos, table)
+   cpufreq_for_each_valid_entry(pos, policy->freq_table)
if (freq_table_get_index(stats, pos->frequency) == -1)
stats->freq_table[i++] = pos->frequency;
 
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index a97ebb7bf27f..2c169fee693e 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -740,14 +740,14 @@ __cpufreq_cooling_register(struct device_node *np,
struct thermal_cooling_device *cdev;
struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH];
-   struct cpufreq_frequency_table *pos, *table;
unsigned int freq, i, num_cpus;
int ret;
struct thermal_cooling_device_ops *cooling_ops;
 
-   table = policy->freq_table;
-   if (!table) {
-   pr_debug("%s: CPUFreq table not found\n", __func__);
+   i = cpufreq_table_count_valid_entries(policy);
+   if (!i) {
+   pr_debug("%s: CPUFreq table not found or has no valid 
entries\n",
+__func__);
return ERR_PTR(-ENODEV);
}
 
@@ -772,20 +772,16 @@ __cpufreq_cooling_register(struct device_node *np,
goto free_time_in_idle;
}
 
-   /* Find max levels */
-   cpufreq_for_each_valid_entry(pos, table)
-   cpufreq_dev->max_level++;
+   /* max_level is an index, not a counter */
+   cpufreq_dev->max_level = i - 1;
 
-   cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
- cpufreq_dev->max_level, GFP_KERNEL);
+   cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) * i,
+ GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
cdev = ERR_PTR(-ENOMEM);
goto free_time_in_idle_timestamp;
}
 
-   /* max_level is an index, not a counter */
-   cpufreq_dev->max_level--;
-
cpumask_copy(_dev->allowed_cpus, policy->related_cpus);
 
if (capacitance) {
@@ -811,7 +807,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
/* Fill freq-table in descending order of frequencies */
for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
-   freq = find_next_max(table, freq);
+   freq = find_next_max(policy->freq_table, freq);
cpufreq_dev->freq_table[i] = freq;
 
/* Warn for duplicate entries */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 87165f06a307..affc13568af6 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -855,6 +855,20 @@ static inline int cpufreq_frequency_table_target(struct 
cpufreq_policy *policy,
return -EINVAL;
}
 }
+
+static inline int cpufreq_table_count_valid_entries(const struct 
cpufreq_policy *policy)
+{
+   struct cpufreq_frequency_table *pos;
+   int count = 0;
+
+   if (unlikely(!policy->freq_table))
+   return 0;
+
+   cpufreq_for_each_valid_entry(pos, policy->freq_table)
+   count++;
+
+   return count;
+}
 #else
 static inline int cpufreq_boost_trigger_state(int state)
 {
-- 
2.7.1.410.g6faf27b



[PATCH 08/17] cpufreq: create cpufreq_table_count_valid_entries()

2017-03-15 Thread Viresh Kumar
We need such a routine at two places already, lets create one.

Signed-off-by: Viresh Kumar 
---
 drivers/cpufreq/cpufreq_stats.c | 13 -
 drivers/thermal/cpu_cooling.c   | 22 +-
 include/linux/cpufreq.h | 14 ++
 3 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index f570ead62454..9c3d319dc129 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -170,11 +170,10 @@ void cpufreq_stats_create_table(struct cpufreq_policy 
*policy)
unsigned int i = 0, count = 0, ret = -ENOMEM;
struct cpufreq_stats *stats;
unsigned int alloc_size;
-   struct cpufreq_frequency_table *pos, *table;
+   struct cpufreq_frequency_table *pos;
 
-   /* We need cpufreq table for creating stats table */
-   table = policy->freq_table;
-   if (unlikely(!table))
+   count = cpufreq_table_count_valid_entries(policy);
+   if (!count)
return;
 
/* stats already initialized */
@@ -185,10 +184,6 @@ void cpufreq_stats_create_table(struct cpufreq_policy 
*policy)
if (!stats)
return;
 
-   /* Find total allocation size */
-   cpufreq_for_each_valid_entry(pos, table)
-   count++;
-
alloc_size = count * sizeof(int) + count * sizeof(u64);
 
alloc_size += count * count * sizeof(int);
@@ -205,7 +200,7 @@ void cpufreq_stats_create_table(struct cpufreq_policy 
*policy)
stats->max_state = count;
 
/* Find valid-unique entries */
-   cpufreq_for_each_valid_entry(pos, table)
+   cpufreq_for_each_valid_entry(pos, policy->freq_table)
if (freq_table_get_index(stats, pos->frequency) == -1)
stats->freq_table[i++] = pos->frequency;
 
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index a97ebb7bf27f..2c169fee693e 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -740,14 +740,14 @@ __cpufreq_cooling_register(struct device_node *np,
struct thermal_cooling_device *cdev;
struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH];
-   struct cpufreq_frequency_table *pos, *table;
unsigned int freq, i, num_cpus;
int ret;
struct thermal_cooling_device_ops *cooling_ops;
 
-   table = policy->freq_table;
-   if (!table) {
-   pr_debug("%s: CPUFreq table not found\n", __func__);
+   i = cpufreq_table_count_valid_entries(policy);
+   if (!i) {
+   pr_debug("%s: CPUFreq table not found or has no valid 
entries\n",
+__func__);
return ERR_PTR(-ENODEV);
}
 
@@ -772,20 +772,16 @@ __cpufreq_cooling_register(struct device_node *np,
goto free_time_in_idle;
}
 
-   /* Find max levels */
-   cpufreq_for_each_valid_entry(pos, table)
-   cpufreq_dev->max_level++;
+   /* max_level is an index, not a counter */
+   cpufreq_dev->max_level = i - 1;
 
-   cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
- cpufreq_dev->max_level, GFP_KERNEL);
+   cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) * i,
+ GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
cdev = ERR_PTR(-ENOMEM);
goto free_time_in_idle_timestamp;
}
 
-   /* max_level is an index, not a counter */
-   cpufreq_dev->max_level--;
-
cpumask_copy(_dev->allowed_cpus, policy->related_cpus);
 
if (capacitance) {
@@ -811,7 +807,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
/* Fill freq-table in descending order of frequencies */
for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
-   freq = find_next_max(table, freq);
+   freq = find_next_max(policy->freq_table, freq);
cpufreq_dev->freq_table[i] = freq;
 
/* Warn for duplicate entries */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 87165f06a307..affc13568af6 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -855,6 +855,20 @@ static inline int cpufreq_frequency_table_target(struct 
cpufreq_policy *policy,
return -EINVAL;
}
 }
+
+static inline int cpufreq_table_count_valid_entries(const struct 
cpufreq_policy *policy)
+{
+   struct cpufreq_frequency_table *pos;
+   int count = 0;
+
+   if (unlikely(!policy->freq_table))
+   return 0;
+
+   cpufreq_for_each_valid_entry(pos, policy->freq_table)
+   count++;
+
+   return count;
+}
 #else
 static inline int cpufreq_boost_trigger_state(int state)
 {
-- 
2.7.1.410.g6faf27b



[PATCH 14/17] thermal: cpu_cooling: get_level() can't fail

2017-03-15 Thread Viresh Kumar
The frequency passed to get_level() is returned by cpu_power_to_freq()
and it is guaranteed that get_level() can't fail.

Get rid of error code.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 20 +---
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 69388a903706..fd84802d2e8e 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -120,22 +120,19 @@ static LIST_HEAD(cpufreq_dev_list);
  * @cpufreq_dev: cpufreq_dev for which the property is required
  * @freq: Frequency
  *
- * Return: level on success, THERMAL_CSTATE_INVALID on error.
+ * Return: level corresponding to the frequency.
  */
 static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_dev,
   unsigned int freq)
 {
+   struct freq_table *freq_table = cpufreq_dev->freq_table;
unsigned long level;
 
-   for (level = 0; level <= cpufreq_dev->max_level; level++) {
-   if (freq == cpufreq_dev->freq_table[level].frequency)
-   return level;
-
-   if (freq > cpufreq_dev->freq_table[level].frequency)
+   for (level = 1; level < cpufreq_dev->max_level; level++)
+   if (freq > freq_table[level].frequency)
break;
-   }
 
-   return THERMAL_CSTATE_INVALID;
+   return level - 1;
 }
 
 /**
@@ -624,13 +621,6 @@ static int cpufreq_power2state(struct 
thermal_cooling_device *cdev,
target_freq = cpu_power_to_freq(cpufreq_dev, normalised_power);
 
*state = get_level(cpufreq_dev, target_freq);
-   if (*state == THERMAL_CSTATE_INVALID) {
-   dev_err_ratelimited(>device,
-   "Failed to convert %dKHz for cpu %d into a 
cdev state\n",
-   target_freq, policy->cpu);
-   return -EINVAL;
-   }
-
trace_thermal_power_cpu_limit(policy->related_cpus, target_freq, *state,
  power);
return 0;
-- 
2.7.1.410.g6faf27b



Re: [PATCH] vc04_services: Fixing coding guideline error

2017-03-15 Thread Pushkar Jambhlekar
Any comment?

On Wed, Mar 15, 2017 at 12:01 PM, Pushkar Jambhlekar
 wrote:
> Fixing 'if' block coding style. '{' should follow 'if' for multiline block
>
> Signed-off-by: Pushkar Jambhlekar 
> ---
>  drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c 
> b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
> index 48984ab..ca896a5 100644
> --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
> +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
> @@ -797,8 +797,7 @@ int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T 
> handle, short *peer_ve
>  {
> int32_t ret = -1;
> SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
> -   if (service)
> -   {
> +   if (service) {
> VCHIQ_STATUS_T status;
>
> status = vchiq_get_peer_version(service->handle, 
> peer_version);
> --
> 2.7.4
>



-- 
Jambhlekar Pushkar Arun
M.Tech IIT Roorkee


[PATCH 14/17] thermal: cpu_cooling: get_level() can't fail

2017-03-15 Thread Viresh Kumar
The frequency passed to get_level() is returned by cpu_power_to_freq()
and it is guaranteed that get_level() can't fail.

Get rid of error code.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 20 +---
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 69388a903706..fd84802d2e8e 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -120,22 +120,19 @@ static LIST_HEAD(cpufreq_dev_list);
  * @cpufreq_dev: cpufreq_dev for which the property is required
  * @freq: Frequency
  *
- * Return: level on success, THERMAL_CSTATE_INVALID on error.
+ * Return: level corresponding to the frequency.
  */
 static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_dev,
   unsigned int freq)
 {
+   struct freq_table *freq_table = cpufreq_dev->freq_table;
unsigned long level;
 
-   for (level = 0; level <= cpufreq_dev->max_level; level++) {
-   if (freq == cpufreq_dev->freq_table[level].frequency)
-   return level;
-
-   if (freq > cpufreq_dev->freq_table[level].frequency)
+   for (level = 1; level < cpufreq_dev->max_level; level++)
+   if (freq > freq_table[level].frequency)
break;
-   }
 
-   return THERMAL_CSTATE_INVALID;
+   return level - 1;
 }
 
 /**
@@ -624,13 +621,6 @@ static int cpufreq_power2state(struct 
thermal_cooling_device *cdev,
target_freq = cpu_power_to_freq(cpufreq_dev, normalised_power);
 
*state = get_level(cpufreq_dev, target_freq);
-   if (*state == THERMAL_CSTATE_INVALID) {
-   dev_err_ratelimited(>device,
-   "Failed to convert %dKHz for cpu %d into a 
cdev state\n",
-   target_freq, policy->cpu);
-   return -EINVAL;
-   }
-
trace_thermal_power_cpu_limit(policy->related_cpus, target_freq, *state,
  power);
return 0;
-- 
2.7.1.410.g6faf27b



Re: [PATCH] vc04_services: Fixing coding guideline error

2017-03-15 Thread Pushkar Jambhlekar
Any comment?

On Wed, Mar 15, 2017 at 12:01 PM, Pushkar Jambhlekar
 wrote:
> Fixing 'if' block coding style. '{' should follow 'if' for multiline block
>
> Signed-off-by: Pushkar Jambhlekar 
> ---
>  drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c 
> b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
> index 48984ab..ca896a5 100644
> --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
> +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
> @@ -797,8 +797,7 @@ int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T 
> handle, short *peer_ve
>  {
> int32_t ret = -1;
> SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
> -   if (service)
> -   {
> +   if (service) {
> VCHIQ_STATUS_T status;
>
> status = vchiq_get_peer_version(service->handle, 
> peer_version);
> --
> 2.7.4
>



-- 
Jambhlekar Pushkar Arun
M.Tech IIT Roorkee


[PATCH 15/17] thermal: cpu_cooling: don't store cpu_dev in cpufreq_dev

2017-03-15 Thread Viresh Kumar
'cpu_dev' is used by only one function, get_static_power(), and it
wouldn't be time consuming to get the cpu device structure within it.
This would help removing cpu_dev from struct cpufreq_cooling_device.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 22 ++
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index fd84802d2e8e..fb535fd5aa12 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -87,7 +87,6 @@ struct time_in_idle {
  * @node: list_head to link all cpufreq_cooling_device together.
  * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @idle_time: idle time stats
- * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
  * This structure is required for keeping information of each registered
@@ -104,7 +103,6 @@ struct cpufreq_cooling_device {
struct list_head node;
u32 last_load;
struct time_in_idle *idle_time;
-   struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
 
@@ -256,8 +254,6 @@ static int update_freq_table(struct cpufreq_cooling_device 
*cpufreq_dev,
freq_table[i].power = power;
}
 
-   cpufreq_dev->cpu_dev = dev;
-
return 0;
 }
 
@@ -339,19 +335,22 @@ static int get_static_power(struct cpufreq_cooling_device 
*cpufreq_dev,
 {
struct dev_pm_opp *opp;
unsigned long voltage;
-   struct cpumask *cpumask = cpufreq_dev->policy->related_cpus;
+   struct cpufreq_policy *policy = cpufreq_dev->policy;
+   struct cpumask *cpumask = policy->related_cpus;
unsigned long freq_hz = freq * 1000;
+   struct device *dev;
 
-   if (!cpufreq_dev->plat_get_static_power || !cpufreq_dev->cpu_dev) {
+   if (!cpufreq_dev->plat_get_static_power) {
*power = 0;
return 0;
}
 
-   opp = dev_pm_opp_find_freq_exact(cpufreq_dev->cpu_dev, freq_hz,
-true);
+   dev = get_cpu_device(policy->cpu);
+   WARN_ON(!dev);
+
+   opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true);
if (IS_ERR(opp)) {
-   dev_warn_ratelimited(cpufreq_dev->cpu_dev,
-"Failed to find OPP for frequency %lu: 
%ld\n",
+   dev_warn_ratelimited(dev, "Failed to find OPP for frequency 
%lu: %ld\n",
 freq_hz, PTR_ERR(opp));
return -EINVAL;
}
@@ -360,8 +359,7 @@ static int get_static_power(struct cpufreq_cooling_device 
*cpufreq_dev,
dev_pm_opp_put(opp);
 
if (voltage == 0) {
-   dev_err_ratelimited(cpufreq_dev->cpu_dev,
-   "Failed to get voltage for frequency %lu\n",
+   dev_err_ratelimited(dev, "Failed to get voltage for frequency 
%lu\n",
freq_hz);
return -EINVAL;
}
-- 
2.7.1.410.g6faf27b



[PATCH 15/17] thermal: cpu_cooling: don't store cpu_dev in cpufreq_dev

2017-03-15 Thread Viresh Kumar
'cpu_dev' is used by only one function, get_static_power(), and it
wouldn't be time consuming to get the cpu device structure within it.
This would help removing cpu_dev from struct cpufreq_cooling_device.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 22 ++
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index fd84802d2e8e..fb535fd5aa12 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -87,7 +87,6 @@ struct time_in_idle {
  * @node: list_head to link all cpufreq_cooling_device together.
  * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @idle_time: idle time stats
- * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
  * This structure is required for keeping information of each registered
@@ -104,7 +103,6 @@ struct cpufreq_cooling_device {
struct list_head node;
u32 last_load;
struct time_in_idle *idle_time;
-   struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
 
@@ -256,8 +254,6 @@ static int update_freq_table(struct cpufreq_cooling_device 
*cpufreq_dev,
freq_table[i].power = power;
}
 
-   cpufreq_dev->cpu_dev = dev;
-
return 0;
 }
 
@@ -339,19 +335,22 @@ static int get_static_power(struct cpufreq_cooling_device 
*cpufreq_dev,
 {
struct dev_pm_opp *opp;
unsigned long voltage;
-   struct cpumask *cpumask = cpufreq_dev->policy->related_cpus;
+   struct cpufreq_policy *policy = cpufreq_dev->policy;
+   struct cpumask *cpumask = policy->related_cpus;
unsigned long freq_hz = freq * 1000;
+   struct device *dev;
 
-   if (!cpufreq_dev->plat_get_static_power || !cpufreq_dev->cpu_dev) {
+   if (!cpufreq_dev->plat_get_static_power) {
*power = 0;
return 0;
}
 
-   opp = dev_pm_opp_find_freq_exact(cpufreq_dev->cpu_dev, freq_hz,
-true);
+   dev = get_cpu_device(policy->cpu);
+   WARN_ON(!dev);
+
+   opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true);
if (IS_ERR(opp)) {
-   dev_warn_ratelimited(cpufreq_dev->cpu_dev,
-"Failed to find OPP for frequency %lu: 
%ld\n",
+   dev_warn_ratelimited(dev, "Failed to find OPP for frequency 
%lu: %ld\n",
 freq_hz, PTR_ERR(opp));
return -EINVAL;
}
@@ -360,8 +359,7 @@ static int get_static_power(struct cpufreq_cooling_device 
*cpufreq_dev,
dev_pm_opp_put(opp);
 
if (voltage == 0) {
-   dev_err_ratelimited(cpufreq_dev->cpu_dev,
-   "Failed to get voltage for frequency %lu\n",
+   dev_err_ratelimited(dev, "Failed to get voltage for frequency 
%lu\n",
freq_hz);
return -EINVAL;
}
-- 
2.7.1.410.g6faf27b



[PATCH 17/17] thermal: cpu_cooling: Rearrange struct cpufreq_cooling_device

2017-03-15 Thread Viresh Kumar
This shrinks the size of the structure on arm64 by 8 bytes by avoiding
padding of 4 bytes at two places.

Also add missing doc comment for freq_table

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 768a95bcc392..f31c753ac08f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -75,17 +75,18 @@ struct time_in_idle {
  * struct cpufreq_cooling_device - data for cooling device with cpufreq
  * @id: unique integer value corresponding to each cpufreq_cooling_device
  * registered.
- * @cdev: thermal_cooling_device pointer to keep track of the
- * registered cooling device.
- * @policy: cpufreq policy.
+ * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @cpufreq_state: integer value representing the current state of cpufreq
  * cooling devices.
  * @clipped_freq: integer value representing the absolute value of the clipped
  * frequency.
  * @max_level: maximum cooling level. One less than total number of valid
  * cpufreq frequencies.
+ * @freq_table: Freq table in descending order of frequencies
+ * @cdev: thermal_cooling_device pointer to keep track of the
+ * registered cooling device.
+ * @policy: cpufreq policy.
  * @node: list_head to link all cpufreq_cooling_device together.
- * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @idle_time: idle time stats
  * @plat_get_static_power: callback to calculate the static power
  *
@@ -94,14 +95,14 @@ struct time_in_idle {
  */
 struct cpufreq_cooling_device {
int id;
-   struct thermal_cooling_device *cdev;
-   struct cpufreq_policy *policy;
+   u32 last_load;
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
struct freq_table *freq_table;  /* In descending order */
+   struct thermal_cooling_device *cdev;
+   struct cpufreq_policy *policy;
struct list_head node;
-   u32 last_load;
struct time_in_idle *idle_time;
get_static_t plat_get_static_power;
 };
-- 
2.7.1.410.g6faf27b



[PATCH 13/17] thermal: cpu_cooling: create structure for idle time stats

2017-03-15 Thread Viresh Kumar
We keep two arrays for idle time stats and allocate memory for them
separately. It would be much easier to follow if we create an array of
idle stats structure instead and allocate it once.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 53 ---
 1 file changed, 25 insertions(+), 28 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 960135d85a71..69388a903706 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -62,6 +62,16 @@ struct freq_table {
 };
 
 /**
+ * struct time_in_idle - Idle time stats
+ * @time: previous reading of the absolute time that this cpu was idle
+ * @timestamp: wall time of the last invocation of get_cpu_idle_time_us()
+ */
+struct time_in_idle {
+   u64 time;
+   u64 timestamp;
+};
+
+/**
  * struct cpufreq_cooling_device - data for cooling device with cpufreq
  * @id: unique integer value corresponding to each cpufreq_cooling_device
  * registered.
@@ -76,9 +86,7 @@ struct freq_table {
  * cpufreq frequencies.
  * @node: list_head to link all cpufreq_cooling_device together.
  * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
- * @time_in_idle: previous reading of the absolute time that this cpu was idle
- * @time_in_idle_timestamp: wall time of the last invocation of
- * get_cpu_idle_time_us()
+ * @idle_time: idle time stats
  * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
@@ -95,8 +103,7 @@ struct cpufreq_cooling_device {
struct freq_table *freq_table;  /* In descending order */
struct list_head node;
u32 last_load;
-   u64 *time_in_idle;
-   u64 *time_in_idle_timestamp;
+   struct time_in_idle *idle_time;
struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
@@ -297,18 +304,19 @@ static u32 get_load(struct cpufreq_cooling_device 
*cpufreq_dev, int cpu,
 {
u32 load;
u64 now, now_idle, delta_time, delta_idle;
+   struct time_in_idle *idle_time = _dev->idle_time[cpu_idx];
 
now_idle = get_cpu_idle_time(cpu, , 0);
-   delta_idle = now_idle - cpufreq_dev->time_in_idle[cpu_idx];
-   delta_time = now - cpufreq_dev->time_in_idle_timestamp[cpu_idx];
+   delta_idle = now_idle - idle_time->time;
+   delta_time = now - idle_time->timestamp;
 
if (delta_time <= delta_idle)
load = 0;
else
load = div64_u64(100 * (delta_time - delta_idle), delta_time);
 
-   cpufreq_dev->time_in_idle[cpu_idx] = now_idle;
-   cpufreq_dev->time_in_idle_timestamp[cpu_idx] = now;
+   idle_time->time = now_idle;
+   idle_time->timestamp = now;
 
return load;
 }
@@ -705,22 +713,14 @@ __cpufreq_cooling_register(struct device_node *np,
return ERR_PTR(-ENOMEM);
 
num_cpus = cpumask_weight(policy->related_cpus);
-   cpufreq_dev->time_in_idle = kcalloc(num_cpus,
-   sizeof(*cpufreq_dev->time_in_idle),
-   GFP_KERNEL);
-   if (!cpufreq_dev->time_in_idle) {
+   cpufreq_dev->idle_time = kcalloc(num_cpus,
+sizeof(*cpufreq_dev->idle_time),
+GFP_KERNEL);
+   if (!cpufreq_dev->idle_time) {
cdev = ERR_PTR(-ENOMEM);
goto free_cdev;
}
 
-   cpufreq_dev->time_in_idle_timestamp =
-   kcalloc(num_cpus, sizeof(*cpufreq_dev->time_in_idle_timestamp),
-   GFP_KERNEL);
-   if (!cpufreq_dev->time_in_idle_timestamp) {
-   cdev = ERR_PTR(-ENOMEM);
-   goto free_time_in_idle;
-   }
-
/* max_level is an index, not a counter */
cpufreq_dev->max_level = i - 1;
 
@@ -728,7 +728,7 @@ __cpufreq_cooling_register(struct device_node *np,
  GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
cdev = ERR_PTR(-ENOMEM);
-   goto free_time_in_idle_timestamp;
+   goto free_idle_time;
}
 
if (capacitance) {
@@ -791,10 +791,8 @@ __cpufreq_cooling_register(struct device_node *np,
ida_simple_remove(_ida, cpufreq_dev->id);
 free_table:
kfree(cpufreq_dev->freq_table);
-free_time_in_idle_timestamp:
-   kfree(cpufreq_dev->time_in_idle_timestamp);
-free_time_in_idle:
-   kfree(cpufreq_dev->time_in_idle);
+free_idle_time:
+   kfree(cpufreq_dev->idle_time);
 free_cdev:
kfree(cpufreq_dev);
return cdev;
@@ -935,8 +933,7 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 
thermal_cooling_device_unregister(cpufreq_dev->cdev);
ida_simple_remove(_ida, cpufreq_dev->id);
-   kfree(cpufreq_dev->time_in_idle_timestamp);
-   

[PATCH 16/17] thermal: cpu_cooling: 'freq' can't be zero in cpufreq_state2power()

2017-03-15 Thread Viresh Kumar
The frequency table shouldn't have any zero frequency entries and so
such a check isn't required. Though it would be better to make sure
'state' is within limits.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index fb535fd5aa12..768a95bcc392 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -561,12 +561,13 @@ static int cpufreq_state2power(struct 
thermal_cooling_device *cdev,
int ret;
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
 
+   /* Request state should be less than max_level */
+   if (WARN_ON(state > cpufreq_dev->max_level))
+   return -EINVAL;
+
num_cpus = cpumask_weight(cpufreq_dev->policy->cpus);
 
freq = cpufreq_dev->freq_table[state].frequency;
-   if (!freq)
-   return -EINVAL;
-
dynamic_power = cpu_freq_to_power(cpufreq_dev, freq) * num_cpus;
ret = get_static_power(cpufreq_dev, tz, freq, _power);
if (ret)
-- 
2.7.1.410.g6faf27b



[PATCH 13/17] thermal: cpu_cooling: create structure for idle time stats

2017-03-15 Thread Viresh Kumar
We keep two arrays for idle time stats and allocate memory for them
separately. It would be much easier to follow if we create an array of
idle stats structure instead and allocate it once.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 53 ---
 1 file changed, 25 insertions(+), 28 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 960135d85a71..69388a903706 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -62,6 +62,16 @@ struct freq_table {
 };
 
 /**
+ * struct time_in_idle - Idle time stats
+ * @time: previous reading of the absolute time that this cpu was idle
+ * @timestamp: wall time of the last invocation of get_cpu_idle_time_us()
+ */
+struct time_in_idle {
+   u64 time;
+   u64 timestamp;
+};
+
+/**
  * struct cpufreq_cooling_device - data for cooling device with cpufreq
  * @id: unique integer value corresponding to each cpufreq_cooling_device
  * registered.
@@ -76,9 +86,7 @@ struct freq_table {
  * cpufreq frequencies.
  * @node: list_head to link all cpufreq_cooling_device together.
  * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
- * @time_in_idle: previous reading of the absolute time that this cpu was idle
- * @time_in_idle_timestamp: wall time of the last invocation of
- * get_cpu_idle_time_us()
+ * @idle_time: idle time stats
  * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
@@ -95,8 +103,7 @@ struct cpufreq_cooling_device {
struct freq_table *freq_table;  /* In descending order */
struct list_head node;
u32 last_load;
-   u64 *time_in_idle;
-   u64 *time_in_idle_timestamp;
+   struct time_in_idle *idle_time;
struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
@@ -297,18 +304,19 @@ static u32 get_load(struct cpufreq_cooling_device 
*cpufreq_dev, int cpu,
 {
u32 load;
u64 now, now_idle, delta_time, delta_idle;
+   struct time_in_idle *idle_time = _dev->idle_time[cpu_idx];
 
now_idle = get_cpu_idle_time(cpu, , 0);
-   delta_idle = now_idle - cpufreq_dev->time_in_idle[cpu_idx];
-   delta_time = now - cpufreq_dev->time_in_idle_timestamp[cpu_idx];
+   delta_idle = now_idle - idle_time->time;
+   delta_time = now - idle_time->timestamp;
 
if (delta_time <= delta_idle)
load = 0;
else
load = div64_u64(100 * (delta_time - delta_idle), delta_time);
 
-   cpufreq_dev->time_in_idle[cpu_idx] = now_idle;
-   cpufreq_dev->time_in_idle_timestamp[cpu_idx] = now;
+   idle_time->time = now_idle;
+   idle_time->timestamp = now;
 
return load;
 }
@@ -705,22 +713,14 @@ __cpufreq_cooling_register(struct device_node *np,
return ERR_PTR(-ENOMEM);
 
num_cpus = cpumask_weight(policy->related_cpus);
-   cpufreq_dev->time_in_idle = kcalloc(num_cpus,
-   sizeof(*cpufreq_dev->time_in_idle),
-   GFP_KERNEL);
-   if (!cpufreq_dev->time_in_idle) {
+   cpufreq_dev->idle_time = kcalloc(num_cpus,
+sizeof(*cpufreq_dev->idle_time),
+GFP_KERNEL);
+   if (!cpufreq_dev->idle_time) {
cdev = ERR_PTR(-ENOMEM);
goto free_cdev;
}
 
-   cpufreq_dev->time_in_idle_timestamp =
-   kcalloc(num_cpus, sizeof(*cpufreq_dev->time_in_idle_timestamp),
-   GFP_KERNEL);
-   if (!cpufreq_dev->time_in_idle_timestamp) {
-   cdev = ERR_PTR(-ENOMEM);
-   goto free_time_in_idle;
-   }
-
/* max_level is an index, not a counter */
cpufreq_dev->max_level = i - 1;
 
@@ -728,7 +728,7 @@ __cpufreq_cooling_register(struct device_node *np,
  GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
cdev = ERR_PTR(-ENOMEM);
-   goto free_time_in_idle_timestamp;
+   goto free_idle_time;
}
 
if (capacitance) {
@@ -791,10 +791,8 @@ __cpufreq_cooling_register(struct device_node *np,
ida_simple_remove(_ida, cpufreq_dev->id);
 free_table:
kfree(cpufreq_dev->freq_table);
-free_time_in_idle_timestamp:
-   kfree(cpufreq_dev->time_in_idle_timestamp);
-free_time_in_idle:
-   kfree(cpufreq_dev->time_in_idle);
+free_idle_time:
+   kfree(cpufreq_dev->idle_time);
 free_cdev:
kfree(cpufreq_dev);
return cdev;
@@ -935,8 +933,7 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 
thermal_cooling_device_unregister(cpufreq_dev->cdev);
ida_simple_remove(_ida, cpufreq_dev->id);
-   kfree(cpufreq_dev->time_in_idle_timestamp);
-   kfree(cpufreq_dev->time_in_idle);

[PATCH 16/17] thermal: cpu_cooling: 'freq' can't be zero in cpufreq_state2power()

2017-03-15 Thread Viresh Kumar
The frequency table shouldn't have any zero frequency entries and so
such a check isn't required. Though it would be better to make sure
'state' is within limits.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index fb535fd5aa12..768a95bcc392 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -561,12 +561,13 @@ static int cpufreq_state2power(struct 
thermal_cooling_device *cdev,
int ret;
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
 
+   /* Request state should be less than max_level */
+   if (WARN_ON(state > cpufreq_dev->max_level))
+   return -EINVAL;
+
num_cpus = cpumask_weight(cpufreq_dev->policy->cpus);
 
freq = cpufreq_dev->freq_table[state].frequency;
-   if (!freq)
-   return -EINVAL;
-
dynamic_power = cpu_freq_to_power(cpufreq_dev, freq) * num_cpus;
ret = get_static_power(cpufreq_dev, tz, freq, _power);
if (ret)
-- 
2.7.1.410.g6faf27b



[PATCH 17/17] thermal: cpu_cooling: Rearrange struct cpufreq_cooling_device

2017-03-15 Thread Viresh Kumar
This shrinks the size of the structure on arm64 by 8 bytes by avoiding
padding of 4 bytes at two places.

Also add missing doc comment for freq_table

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 768a95bcc392..f31c753ac08f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -75,17 +75,18 @@ struct time_in_idle {
  * struct cpufreq_cooling_device - data for cooling device with cpufreq
  * @id: unique integer value corresponding to each cpufreq_cooling_device
  * registered.
- * @cdev: thermal_cooling_device pointer to keep track of the
- * registered cooling device.
- * @policy: cpufreq policy.
+ * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @cpufreq_state: integer value representing the current state of cpufreq
  * cooling devices.
  * @clipped_freq: integer value representing the absolute value of the clipped
  * frequency.
  * @max_level: maximum cooling level. One less than total number of valid
  * cpufreq frequencies.
+ * @freq_table: Freq table in descending order of frequencies
+ * @cdev: thermal_cooling_device pointer to keep track of the
+ * registered cooling device.
+ * @policy: cpufreq policy.
  * @node: list_head to link all cpufreq_cooling_device together.
- * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @idle_time: idle time stats
  * @plat_get_static_power: callback to calculate the static power
  *
@@ -94,14 +95,14 @@ struct time_in_idle {
  */
 struct cpufreq_cooling_device {
int id;
-   struct thermal_cooling_device *cdev;
-   struct cpufreq_policy *policy;
+   u32 last_load;
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
struct freq_table *freq_table;  /* In descending order */
+   struct thermal_cooling_device *cdev;
+   struct cpufreq_policy *policy;
struct list_head node;
-   u32 last_load;
struct time_in_idle *idle_time;
get_static_t plat_get_static_power;
 };
-- 
2.7.1.410.g6faf27b



[PATCH 06/17] thermal: cpu_cooling: get rid of a variable in cpufreq_set_cur_state()

2017-03-15 Thread Viresh Kumar
'cpu' is used at only one place and there is no need to keep a separate
variable for it.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 99dc6833de75..46e90122b746 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -457,7 +457,6 @@ static int cpufreq_set_cur_state(struct 
thermal_cooling_device *cdev,
 unsigned long state)
 {
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
-   unsigned int cpu = cpumask_any(_dev->allowed_cpus);
unsigned int clip_freq;
 
/* Request state should be less than max_level */
@@ -472,7 +471,7 @@ static int cpufreq_set_cur_state(struct 
thermal_cooling_device *cdev,
cpufreq_dev->cpufreq_state = state;
cpufreq_dev->clipped_freq = clip_freq;
 
-   cpufreq_update_policy(cpu);
+   cpufreq_update_policy(cpumask_any(_dev->allowed_cpus));
 
return 0;
 }
-- 
2.7.1.410.g6faf27b



[PATCH 12/17] thermal: cpu_cooling: merge frequency and power tables

2017-03-15 Thread Viresh Kumar
The cpu_cooling driver keeps two tables:

- freq_table: table of frequencies in descending order, built from
  policy->freq_table.

- power_table: table of frequencies and power in ascending order, built
  from OPP table.

If the OPPs are used for the CPU device then both these tables are
actually built using the OPP core and should have the same frequency
entries. And there is no need to keep separate tables for this.

Lets merge them both.

Note that the new table is in descending order of frequencies and so the
'for' loops were required to be fixed at few places to make it work.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 123 ++
 1 file changed, 52 insertions(+), 71 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index b7b193cb0e7a..960135d85a71 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -49,14 +49,14 @@
  */
 
 /**
- * struct power_table - frequency to power conversion
+ * struct freq_table - frequency table along with power entries
  * @frequency: frequency in KHz
  * @power: power in mW
  *
  * This structure is built when the cooling device registers and helps
- * in translating frequency to power and viceversa.
+ * in translating frequency to power and vice versa.
  */
-struct power_table {
+struct freq_table {
u32 frequency;
u32 power;
 };
@@ -79,9 +79,6 @@ struct power_table {
  * @time_in_idle: previous reading of the absolute time that this cpu was idle
  * @time_in_idle_timestamp: wall time of the last invocation of
  * get_cpu_idle_time_us()
- * @dyn_power_table: array of struct power_table for frequency to power
- * conversion, sorted in ascending order.
- * @dyn_power_table_entries: number of entries in the @dyn_power_table array
  * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
@@ -95,13 +92,11 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
-   unsigned int *freq_table;   /* In descending order */
+   struct freq_table *freq_table;  /* In descending order */
struct list_head node;
u32 last_load;
u64 *time_in_idle;
u64 *time_in_idle_timestamp;
-   struct power_table *dyn_power_table;
-   int dyn_power_table_entries;
struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
@@ -126,10 +121,10 @@ static unsigned long get_level(struct 
cpufreq_cooling_device *cpufreq_dev,
unsigned long level;
 
for (level = 0; level <= cpufreq_dev->max_level; level++) {
-   if (freq == cpufreq_dev->freq_table[level])
+   if (freq == cpufreq_dev->freq_table[level].frequency)
return level;
 
-   if (freq > cpufreq_dev->freq_table[level])
+   if (freq > cpufreq_dev->freq_table[level].frequency)
break;
}
 
@@ -186,28 +181,25 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 }
 
 /**
- * build_dyn_power_table() - create a dynamic power to frequency table
- * @cpufreq_dev:   the cpufreq cooling device in which to store the table
+ * update_freq_table() - Update the freq table with power numbers
+ * @cpufreq_dev:   the cpufreq cooling device in which to update the table
  * @capacitance: dynamic power coefficient for these cpus
  *
- * Build a dynamic power to frequency table for this cpu and store it
- * in @cpufreq_dev.  This table will be used in cpu_power_to_freq() and
- * cpu_freq_to_power() to convert between power and frequency
- * efficiently.  Power is stored in mW, frequency in KHz.  The
- * resulting table is in ascending order.
+ * Update the freq table with power numbers.  This table will be used in
+ * cpu_power_to_freq() and cpu_freq_to_power() to convert between power and
+ * frequency efficiently.  Power is stored in mW, frequency in KHz.  The
+ * resulting table is in descending order.
  *
  * Return: 0 on success, -EINVAL if there are no OPPs for any CPUs,
- * -ENOMEM if we run out of memory or -EAGAIN if an OPP was
- * added/enabled while the function was executing.
+ * or -ENOMEM if we run out of memory.
  */
-static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_dev,
-u32 capacitance)
+static int update_freq_table(struct cpufreq_cooling_device *cpufreq_dev,
+u32 capacitance)
 {
-   struct power_table *power_table;
+   struct freq_table *freq_table = cpufreq_dev->freq_table;
struct dev_pm_opp *opp;
struct device *dev = NULL;
-   int num_opps = 0, cpu = cpufreq_dev->policy->cpu, i, ret = 0;
-   unsigned long freq;
+   int num_opps = 0, cpu = cpufreq_dev->policy->cpu, i;
 
dev = get_cpu_device(cpu);
if 

[PATCH 05/17] thermal: cpu_cooling: remove cpufreq_cooling_get_level()

2017-03-15 Thread Viresh Kumar
There is only one user of cpufreq_cooling_get_level() and that already
has pointer to the cpufreq_dev structure. It can directly call
get_level() instead and we can get rid of cpufreq_cooling_get_level().

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 33 +
 include/linux/cpu_cooling.h   |  6 --
 2 files changed, 1 insertion(+), 38 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index e2931c20c309..99dc6833de75 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -137,37 +137,6 @@ static unsigned long get_level(struct 
cpufreq_cooling_device *cpufreq_dev,
 }
 
 /**
- * cpufreq_cooling_get_level - for a given cpu, return the cooling level.
- * @cpu: cpu for which the level is required
- * @freq: the frequency of interest
- *
- * This function will match the cooling level corresponding to the
- * requested @freq and return it.
- *
- * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID
- * otherwise.
- */
-unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
-{
-   struct cpufreq_cooling_device *cpufreq_dev;
-
-   mutex_lock(_list_lock);
-   list_for_each_entry(cpufreq_dev, _dev_list, node) {
-   if (cpumask_test_cpu(cpu, _dev->allowed_cpus)) {
-   unsigned long level = get_level(cpufreq_dev, freq);
-
-   mutex_unlock(_list_lock);
-   return level;
-   }
-   }
-   mutex_unlock(_list_lock);
-
-   pr_err("%s: cpu:%d not part of any cooling device\n", __func__, cpu);
-   return THERMAL_CSTATE_INVALID;
-}
-EXPORT_SYMBOL_GPL(cpufreq_cooling_get_level);
-
-/**
  * cpufreq_thermal_notifier - notifier callback for cpufreq policy change.
  * @nb:struct notifier_block * with callback info.
  * @event: value showing cpufreq event for which this function invoked.
@@ -698,7 +667,7 @@ static int cpufreq_power2state(struct 
thermal_cooling_device *cdev,
normalised_power = (dyn_power * 100) / last_load;
target_freq = cpu_power_to_freq(cpufreq_dev, normalised_power);
 
-   *state = cpufreq_cooling_get_level(cpu, target_freq);
+   *state = get_level(cpufreq_dev, target_freq);
if (*state == THERMAL_CSTATE_INVALID) {
dev_err_ratelimited(>device,
"Failed to convert %dKHz for cpu %d into a 
cdev state\n",
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index c156f5082758..96c5e4c2f9c8 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -82,7 +82,6 @@ of_cpufreq_power_cooling_register(struct device_node *np,
  */
 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
 
-unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq);
 #else /* !CONFIG_CPU_THERMAL */
 static inline struct thermal_cooling_device *
 cpufreq_cooling_register(const struct cpumask *clip_cpus)
@@ -117,11 +116,6 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 {
return;
 }
-static inline
-unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
-{
-   return THERMAL_CSTATE_INVALID;
-}
 #endif /* CONFIG_CPU_THERMAL */
 
 #endif /* __CPU_COOLING_H__ */
-- 
2.7.1.410.g6faf27b



[PATCH 09/17] thermal: cpu_cooling: store cpufreq policy

2017-03-15 Thread Viresh Kumar
The cpufreq policy can be used by the cpu_cooling driver, lets store it
in the cpufreq_cooling_device structure.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 2c169fee693e..7590279bf1de 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -67,6 +67,7 @@ struct power_table {
  * registered.
  * @cdev: thermal_cooling_device pointer to keep track of the
  * registered cooling device.
+ * @policy: cpufreq policy.
  * @cpufreq_state: integer value representing the current state of cpufreq
  * cooling devices.
  * @clipped_freq: integer value representing the absolute value of the clipped
@@ -91,6 +92,7 @@ struct power_table {
 struct cpufreq_cooling_device {
int id;
struct thermal_cooling_device *cdev;
+   struct cpufreq_policy *policy;
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
@@ -827,6 +829,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
cpufreq_dev->cdev = cdev;
+   cpufreq_dev->policy = policy;
 
mutex_lock(_list_lock);
list_add(_dev->node, _dev_list);
-- 
2.7.1.410.g6faf27b



[PATCH 06/17] thermal: cpu_cooling: get rid of a variable in cpufreq_set_cur_state()

2017-03-15 Thread Viresh Kumar
'cpu' is used at only one place and there is no need to keep a separate
variable for it.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 99dc6833de75..46e90122b746 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -457,7 +457,6 @@ static int cpufreq_set_cur_state(struct 
thermal_cooling_device *cdev,
 unsigned long state)
 {
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
-   unsigned int cpu = cpumask_any(_dev->allowed_cpus);
unsigned int clip_freq;
 
/* Request state should be less than max_level */
@@ -472,7 +471,7 @@ static int cpufreq_set_cur_state(struct 
thermal_cooling_device *cdev,
cpufreq_dev->cpufreq_state = state;
cpufreq_dev->clipped_freq = clip_freq;
 
-   cpufreq_update_policy(cpu);
+   cpufreq_update_policy(cpumask_any(_dev->allowed_cpus));
 
return 0;
 }
-- 
2.7.1.410.g6faf27b



[PATCH 12/17] thermal: cpu_cooling: merge frequency and power tables

2017-03-15 Thread Viresh Kumar
The cpu_cooling driver keeps two tables:

- freq_table: table of frequencies in descending order, built from
  policy->freq_table.

- power_table: table of frequencies and power in ascending order, built
  from OPP table.

If the OPPs are used for the CPU device then both these tables are
actually built using the OPP core and should have the same frequency
entries. And there is no need to keep separate tables for this.

Lets merge them both.

Note that the new table is in descending order of frequencies and so the
'for' loops were required to be fixed at few places to make it work.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 123 ++
 1 file changed, 52 insertions(+), 71 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index b7b193cb0e7a..960135d85a71 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -49,14 +49,14 @@
  */
 
 /**
- * struct power_table - frequency to power conversion
+ * struct freq_table - frequency table along with power entries
  * @frequency: frequency in KHz
  * @power: power in mW
  *
  * This structure is built when the cooling device registers and helps
- * in translating frequency to power and viceversa.
+ * in translating frequency to power and vice versa.
  */
-struct power_table {
+struct freq_table {
u32 frequency;
u32 power;
 };
@@ -79,9 +79,6 @@ struct power_table {
  * @time_in_idle: previous reading of the absolute time that this cpu was idle
  * @time_in_idle_timestamp: wall time of the last invocation of
  * get_cpu_idle_time_us()
- * @dyn_power_table: array of struct power_table for frequency to power
- * conversion, sorted in ascending order.
- * @dyn_power_table_entries: number of entries in the @dyn_power_table array
  * @cpu_dev: the cpu_device of policy->cpu.
  * @plat_get_static_power: callback to calculate the static power
  *
@@ -95,13 +92,11 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
-   unsigned int *freq_table;   /* In descending order */
+   struct freq_table *freq_table;  /* In descending order */
struct list_head node;
u32 last_load;
u64 *time_in_idle;
u64 *time_in_idle_timestamp;
-   struct power_table *dyn_power_table;
-   int dyn_power_table_entries;
struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
@@ -126,10 +121,10 @@ static unsigned long get_level(struct 
cpufreq_cooling_device *cpufreq_dev,
unsigned long level;
 
for (level = 0; level <= cpufreq_dev->max_level; level++) {
-   if (freq == cpufreq_dev->freq_table[level])
+   if (freq == cpufreq_dev->freq_table[level].frequency)
return level;
 
-   if (freq > cpufreq_dev->freq_table[level])
+   if (freq > cpufreq_dev->freq_table[level].frequency)
break;
}
 
@@ -186,28 +181,25 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 }
 
 /**
- * build_dyn_power_table() - create a dynamic power to frequency table
- * @cpufreq_dev:   the cpufreq cooling device in which to store the table
+ * update_freq_table() - Update the freq table with power numbers
+ * @cpufreq_dev:   the cpufreq cooling device in which to update the table
  * @capacitance: dynamic power coefficient for these cpus
  *
- * Build a dynamic power to frequency table for this cpu and store it
- * in @cpufreq_dev.  This table will be used in cpu_power_to_freq() and
- * cpu_freq_to_power() to convert between power and frequency
- * efficiently.  Power is stored in mW, frequency in KHz.  The
- * resulting table is in ascending order.
+ * Update the freq table with power numbers.  This table will be used in
+ * cpu_power_to_freq() and cpu_freq_to_power() to convert between power and
+ * frequency efficiently.  Power is stored in mW, frequency in KHz.  The
+ * resulting table is in descending order.
  *
  * Return: 0 on success, -EINVAL if there are no OPPs for any CPUs,
- * -ENOMEM if we run out of memory or -EAGAIN if an OPP was
- * added/enabled while the function was executing.
+ * or -ENOMEM if we run out of memory.
  */
-static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_dev,
-u32 capacitance)
+static int update_freq_table(struct cpufreq_cooling_device *cpufreq_dev,
+u32 capacitance)
 {
-   struct power_table *power_table;
+   struct freq_table *freq_table = cpufreq_dev->freq_table;
struct dev_pm_opp *opp;
struct device *dev = NULL;
-   int num_opps = 0, cpu = cpufreq_dev->policy->cpu, i, ret = 0;
-   unsigned long freq;
+   int num_opps = 0, cpu = cpufreq_dev->policy->cpu, i;
 
dev = get_cpu_device(cpu);
if (unlikely(!dev)) {
@@ -220,25 

[PATCH 05/17] thermal: cpu_cooling: remove cpufreq_cooling_get_level()

2017-03-15 Thread Viresh Kumar
There is only one user of cpufreq_cooling_get_level() and that already
has pointer to the cpufreq_dev structure. It can directly call
get_level() instead and we can get rid of cpufreq_cooling_get_level().

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 33 +
 include/linux/cpu_cooling.h   |  6 --
 2 files changed, 1 insertion(+), 38 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index e2931c20c309..99dc6833de75 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -137,37 +137,6 @@ static unsigned long get_level(struct 
cpufreq_cooling_device *cpufreq_dev,
 }
 
 /**
- * cpufreq_cooling_get_level - for a given cpu, return the cooling level.
- * @cpu: cpu for which the level is required
- * @freq: the frequency of interest
- *
- * This function will match the cooling level corresponding to the
- * requested @freq and return it.
- *
- * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID
- * otherwise.
- */
-unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
-{
-   struct cpufreq_cooling_device *cpufreq_dev;
-
-   mutex_lock(_list_lock);
-   list_for_each_entry(cpufreq_dev, _dev_list, node) {
-   if (cpumask_test_cpu(cpu, _dev->allowed_cpus)) {
-   unsigned long level = get_level(cpufreq_dev, freq);
-
-   mutex_unlock(_list_lock);
-   return level;
-   }
-   }
-   mutex_unlock(_list_lock);
-
-   pr_err("%s: cpu:%d not part of any cooling device\n", __func__, cpu);
-   return THERMAL_CSTATE_INVALID;
-}
-EXPORT_SYMBOL_GPL(cpufreq_cooling_get_level);
-
-/**
  * cpufreq_thermal_notifier - notifier callback for cpufreq policy change.
  * @nb:struct notifier_block * with callback info.
  * @event: value showing cpufreq event for which this function invoked.
@@ -698,7 +667,7 @@ static int cpufreq_power2state(struct 
thermal_cooling_device *cdev,
normalised_power = (dyn_power * 100) / last_load;
target_freq = cpu_power_to_freq(cpufreq_dev, normalised_power);
 
-   *state = cpufreq_cooling_get_level(cpu, target_freq);
+   *state = get_level(cpufreq_dev, target_freq);
if (*state == THERMAL_CSTATE_INVALID) {
dev_err_ratelimited(>device,
"Failed to convert %dKHz for cpu %d into a 
cdev state\n",
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index c156f5082758..96c5e4c2f9c8 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -82,7 +82,6 @@ of_cpufreq_power_cooling_register(struct device_node *np,
  */
 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
 
-unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq);
 #else /* !CONFIG_CPU_THERMAL */
 static inline struct thermal_cooling_device *
 cpufreq_cooling_register(const struct cpumask *clip_cpus)
@@ -117,11 +116,6 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 {
return;
 }
-static inline
-unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
-{
-   return THERMAL_CSTATE_INVALID;
-}
 #endif /* CONFIG_CPU_THERMAL */
 
 #endif /* __CPU_COOLING_H__ */
-- 
2.7.1.410.g6faf27b



[PATCH 09/17] thermal: cpu_cooling: store cpufreq policy

2017-03-15 Thread Viresh Kumar
The cpufreq policy can be used by the cpu_cooling driver, lets store it
in the cpufreq_cooling_device structure.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 2c169fee693e..7590279bf1de 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -67,6 +67,7 @@ struct power_table {
  * registered.
  * @cdev: thermal_cooling_device pointer to keep track of the
  * registered cooling device.
+ * @policy: cpufreq policy.
  * @cpufreq_state: integer value representing the current state of cpufreq
  * cooling devices.
  * @clipped_freq: integer value representing the absolute value of the clipped
@@ -91,6 +92,7 @@ struct power_table {
 struct cpufreq_cooling_device {
int id;
struct thermal_cooling_device *cdev;
+   struct cpufreq_policy *policy;
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
@@ -827,6 +829,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
cpufreq_dev->cdev = cdev;
+   cpufreq_dev->policy = policy;
 
mutex_lock(_list_lock);
list_add(_dev->node, _dev_list);
-- 
2.7.1.410.g6faf27b



[PATCH 02/17] thermal: cpu_cooling: rearrange globals

2017-03-15 Thread Viresh Kumar
Just to make it look better.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 6fd258d62e47..7ce73eee866f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -105,10 +105,9 @@ struct cpufreq_cooling_device {
struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
-static DEFINE_IDA(cpufreq_ida);
 
 static unsigned int cpufreq_dev_count;
-
+static DEFINE_IDA(cpufreq_ida);
 static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
-- 
2.7.1.410.g6faf27b



[PATCH 11/17] thermal: cpu_cooling: get rid of 'allowed_cpus'

2017-03-15 Thread Viresh Kumar
'allowed_cpus' is a copy of policy->related_cpus and can be replaced by
it directly. At some places we are only concerned about online CPUs and
policy->cpus can be used there.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 77 ---
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 1df6c9039e45..b7b193cb0e7a 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -74,7 +74,6 @@ struct power_table {
  * frequency.
  * @max_level: maximum cooling level. One less than total number of valid
  * cpufreq frequencies.
- * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
  * @node: list_head to link all cpufreq_cooling_device together.
  * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @time_in_idle: previous reading of the absolute time that this cpu was idle
@@ -97,7 +96,6 @@ struct cpufreq_cooling_device {
unsigned int clipped_freq;
unsigned int max_level;
unsigned int *freq_table;   /* In descending order */
-   struct cpumask allowed_cpus;
struct list_head node;
u32 last_load;
u64 *time_in_idle;
@@ -162,7 +160,7 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 
mutex_lock(_list_lock);
list_for_each_entry(cpufreq_dev, _dev_list, node) {
-   if (!cpumask_test_cpu(policy->cpu, _dev->allowed_cpus))
+   if (policy != cpufreq_dev->policy)
continue;
 
/*
@@ -305,7 +303,7 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device 
*cpufreq_dev,
  * get_load() - get load for a cpu since last updated
  * @cpufreq_dev:cpufreq_cooling_device for this cpu
  * @cpu:   cpu number
- * @cpu_idx:   index of the cpu in cpufreq_dev->allowed_cpus
+ * @cpu_idx:   index of the cpu in time_in_idle*
  *
  * Return: The average load of cpu @cpu in percentage since this
  * function was last called.
@@ -352,7 +350,7 @@ static int get_static_power(struct cpufreq_cooling_device 
*cpufreq_dev,
 {
struct dev_pm_opp *opp;
unsigned long voltage;
-   struct cpumask *cpumask = _dev->allowed_cpus;
+   struct cpumask *cpumask = cpufreq_dev->policy->related_cpus;
unsigned long freq_hz = freq * 1000;
 
if (!cpufreq_dev->plat_get_static_power || !cpufreq_dev->cpu_dev) {
@@ -469,7 +467,7 @@ static int cpufreq_set_cur_state(struct 
thermal_cooling_device *cdev,
cpufreq_dev->cpufreq_state = state;
cpufreq_dev->clipped_freq = clip_freq;
 
-   cpufreq_update_policy(cpumask_any(_dev->allowed_cpus));
+   cpufreq_update_policy(cpufreq_dev->policy->cpu);
 
return 0;
 }
@@ -505,28 +503,18 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
int i = 0, cpu, ret;
u32 static_power, dynamic_power, total_load = 0;
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
+   struct cpufreq_policy *policy = cpufreq_dev->policy;
u32 *load_cpu = NULL;
 
-   cpu = cpumask_any_and(_dev->allowed_cpus, cpu_online_mask);
-
-   /*
-* All the CPUs are offline, thus the requested power by
-* the cdev is 0
-*/
-   if (cpu >= nr_cpu_ids) {
-   *power = 0;
-   return 0;
-   }
-
-   freq = cpufreq_quick_get(cpu);
+   freq = cpufreq_quick_get(policy->cpu);
 
if (trace_thermal_power_cpu_get_power_enabled()) {
-   u32 ncpus = cpumask_weight(_dev->allowed_cpus);
+   u32 ncpus = cpumask_weight(policy->related_cpus);
 
load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
}
 
-   for_each_cpu(cpu, _dev->allowed_cpus) {
+   for_each_cpu(cpu, policy->related_cpus) {
u32 load;
 
if (cpu_online(cpu))
@@ -551,9 +539,9 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
}
 
if (load_cpu) {
-   trace_thermal_power_cpu_get_power(
-   _dev->allowed_cpus,
-   freq, load_cpu, i, dynamic_power, static_power);
+   trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
+ load_cpu, i, dynamic_power,
+ static_power);
 
kfree(load_cpu);
}
@@ -582,38 +570,22 @@ static int cpufreq_state2power(struct 
thermal_cooling_device *cdev,
   unsigned long state, u32 *power)
 {
unsigned int freq, num_cpus;
-   cpumask_var_t cpumask;
u32 static_power, dynamic_power;
int ret;
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
 
-   if (!alloc_cpumask_var(, GFP_KERNEL))
-   

[PATCH 04/17] thermal: cpu_cooling: replace cool_dev with cdev

2017-03-15 Thread Viresh Kumar
Objects of "struct thermal_cooling_device" are named a bit
inconsistently. Lets use cdev everywhere.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7a19033d7f79..e2931c20c309 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -65,7 +65,7 @@ struct power_table {
  * struct cpufreq_cooling_device - data for cooling device with cpufreq
  * @id: unique integer value corresponding to each cpufreq_cooling_device
  * registered.
- * @cool_dev: thermal_cooling_device pointer to keep track of the
+ * @cdev: thermal_cooling_device pointer to keep track of the
  * registered cooling device.
  * @cpufreq_state: integer value representing the current state of cpufreq
  * cooling devices.
@@ -90,7 +90,7 @@ struct power_table {
  */
 struct cpufreq_cooling_device {
int id;
-   struct thermal_cooling_device *cool_dev;
+   struct thermal_cooling_device *cdev;
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
@@ -243,7 +243,7 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_dev,
for_each_cpu(cpu, _dev->allowed_cpus) {
dev = get_cpu_device(cpu);
if (!dev) {
-   dev_warn(_dev->cool_dev->device,
+   dev_warn(_dev->cdev->device,
 "No cpu device for cpu %d\n", cpu);
continue;
}
@@ -770,7 +770,7 @@ __cpufreq_cooling_register(struct device_node *np,
get_static_t plat_static_func)
 {
struct cpufreq_policy *policy;
-   struct thermal_cooling_device *cool_dev;
+   struct thermal_cooling_device *cdev;
struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH];
struct cpufreq_frequency_table *pos, *table;
@@ -786,20 +786,20 @@ __cpufreq_cooling_register(struct device_node *np,
policy = cpufreq_cpu_get(cpumask_first(temp_mask));
if (!policy) {
pr_debug("%s: CPUFreq policy not found\n", __func__);
-   cool_dev = ERR_PTR(-EPROBE_DEFER);
+   cdev = ERR_PTR(-EPROBE_DEFER);
goto free_cpumask;
}
 
table = policy->freq_table;
if (!table) {
pr_debug("%s: CPUFreq table not found\n", __func__);
-   cool_dev = ERR_PTR(-ENODEV);
+   cdev = ERR_PTR(-ENODEV);
goto put_policy;
}
 
cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL);
if (!cpufreq_dev) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto put_policy;
}
 
@@ -808,7 +808,7 @@ __cpufreq_cooling_register(struct device_node *np,
sizeof(*cpufreq_dev->time_in_idle),
GFP_KERNEL);
if (!cpufreq_dev->time_in_idle) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto free_cdev;
}
 
@@ -816,7 +816,7 @@ __cpufreq_cooling_register(struct device_node *np,
kcalloc(num_cpus, sizeof(*cpufreq_dev->time_in_idle_timestamp),
GFP_KERNEL);
if (!cpufreq_dev->time_in_idle_timestamp) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto free_time_in_idle;
}
 
@@ -827,7 +827,7 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
  cpufreq_dev->max_level, GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto free_time_in_idle_timestamp;
}
 
@@ -841,7 +841,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
ret = build_dyn_power_table(cpufreq_dev, capacitance);
if (ret) {
-   cool_dev = ERR_PTR(ret);
+   cdev = ERR_PTR(ret);
goto free_table;
}
 
@@ -852,7 +852,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
ret = ida_simple_get(_ida, 0, 0, GFP_KERNEL);
if (ret < 0) {
-   cool_dev = ERR_PTR(ret);
+   cdev = ERR_PTR(ret);
goto free_power_table;
}
cpufreq_dev->id = ret;
@@ -872,13 +872,13 @@ __cpufreq_cooling_register(struct device_node *np,
snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
 cpufreq_dev->id);
 
-   cool_dev = thermal_of_cooling_device_register(np, dev_name, 

[PATCH 01/17] thermal: cpu_cooling: Avoid accessing potentially freed structures

2017-03-15 Thread Viresh Kumar
After the lock is dropped, it is possible that the cpufreq_dev gets
freed before we call get_level() and that can cause kernel to crash.

Drop the lock after we are done using the structure.

Cc: 4.2+ 
Fixes: 02373d7c69b4 ("thermal: cpu_cooling: fix lockdep problems in 
cpu_cooling")
Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index c2525b585487..6fd258d62e47 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -155,8 +155,10 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, 
unsigned int freq)
mutex_lock(_list_lock);
list_for_each_entry(cpufreq_dev, _dev_list, node) {
if (cpumask_test_cpu(cpu, _dev->allowed_cpus)) {
+   unsigned long level = get_level(cpufreq_dev, freq);
+
mutex_unlock(_list_lock);
-   return get_level(cpufreq_dev, freq);
+   return level;
}
}
mutex_unlock(_list_lock);
-- 
2.7.1.410.g6faf27b



[PATCH 02/17] thermal: cpu_cooling: rearrange globals

2017-03-15 Thread Viresh Kumar
Just to make it look better.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 6fd258d62e47..7ce73eee866f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -105,10 +105,9 @@ struct cpufreq_cooling_device {
struct device *cpu_dev;
get_static_t plat_get_static_power;
 };
-static DEFINE_IDA(cpufreq_ida);
 
 static unsigned int cpufreq_dev_count;
-
+static DEFINE_IDA(cpufreq_ida);
 static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
-- 
2.7.1.410.g6faf27b



[PATCH 11/17] thermal: cpu_cooling: get rid of 'allowed_cpus'

2017-03-15 Thread Viresh Kumar
'allowed_cpus' is a copy of policy->related_cpus and can be replaced by
it directly. At some places we are only concerned about online CPUs and
policy->cpus can be used there.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 77 ---
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 1df6c9039e45..b7b193cb0e7a 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -74,7 +74,6 @@ struct power_table {
  * frequency.
  * @max_level: maximum cooling level. One less than total number of valid
  * cpufreq frequencies.
- * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
  * @node: list_head to link all cpufreq_cooling_device together.
  * @last_load: load measured by the latest call to 
cpufreq_get_requested_power()
  * @time_in_idle: previous reading of the absolute time that this cpu was idle
@@ -97,7 +96,6 @@ struct cpufreq_cooling_device {
unsigned int clipped_freq;
unsigned int max_level;
unsigned int *freq_table;   /* In descending order */
-   struct cpumask allowed_cpus;
struct list_head node;
u32 last_load;
u64 *time_in_idle;
@@ -162,7 +160,7 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 
mutex_lock(_list_lock);
list_for_each_entry(cpufreq_dev, _dev_list, node) {
-   if (!cpumask_test_cpu(policy->cpu, _dev->allowed_cpus))
+   if (policy != cpufreq_dev->policy)
continue;
 
/*
@@ -305,7 +303,7 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device 
*cpufreq_dev,
  * get_load() - get load for a cpu since last updated
  * @cpufreq_dev:cpufreq_cooling_device for this cpu
  * @cpu:   cpu number
- * @cpu_idx:   index of the cpu in cpufreq_dev->allowed_cpus
+ * @cpu_idx:   index of the cpu in time_in_idle*
  *
  * Return: The average load of cpu @cpu in percentage since this
  * function was last called.
@@ -352,7 +350,7 @@ static int get_static_power(struct cpufreq_cooling_device 
*cpufreq_dev,
 {
struct dev_pm_opp *opp;
unsigned long voltage;
-   struct cpumask *cpumask = _dev->allowed_cpus;
+   struct cpumask *cpumask = cpufreq_dev->policy->related_cpus;
unsigned long freq_hz = freq * 1000;
 
if (!cpufreq_dev->plat_get_static_power || !cpufreq_dev->cpu_dev) {
@@ -469,7 +467,7 @@ static int cpufreq_set_cur_state(struct 
thermal_cooling_device *cdev,
cpufreq_dev->cpufreq_state = state;
cpufreq_dev->clipped_freq = clip_freq;
 
-   cpufreq_update_policy(cpumask_any(_dev->allowed_cpus));
+   cpufreq_update_policy(cpufreq_dev->policy->cpu);
 
return 0;
 }
@@ -505,28 +503,18 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
int i = 0, cpu, ret;
u32 static_power, dynamic_power, total_load = 0;
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
+   struct cpufreq_policy *policy = cpufreq_dev->policy;
u32 *load_cpu = NULL;
 
-   cpu = cpumask_any_and(_dev->allowed_cpus, cpu_online_mask);
-
-   /*
-* All the CPUs are offline, thus the requested power by
-* the cdev is 0
-*/
-   if (cpu >= nr_cpu_ids) {
-   *power = 0;
-   return 0;
-   }
-
-   freq = cpufreq_quick_get(cpu);
+   freq = cpufreq_quick_get(policy->cpu);
 
if (trace_thermal_power_cpu_get_power_enabled()) {
-   u32 ncpus = cpumask_weight(_dev->allowed_cpus);
+   u32 ncpus = cpumask_weight(policy->related_cpus);
 
load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
}
 
-   for_each_cpu(cpu, _dev->allowed_cpus) {
+   for_each_cpu(cpu, policy->related_cpus) {
u32 load;
 
if (cpu_online(cpu))
@@ -551,9 +539,9 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
}
 
if (load_cpu) {
-   trace_thermal_power_cpu_get_power(
-   _dev->allowed_cpus,
-   freq, load_cpu, i, dynamic_power, static_power);
+   trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
+ load_cpu, i, dynamic_power,
+ static_power);
 
kfree(load_cpu);
}
@@ -582,38 +570,22 @@ static int cpufreq_state2power(struct 
thermal_cooling_device *cdev,
   unsigned long state, u32 *power)
 {
unsigned int freq, num_cpus;
-   cpumask_var_t cpumask;
u32 static_power, dynamic_power;
int ret;
struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
 
-   if (!alloc_cpumask_var(, GFP_KERNEL))
-   return -ENOMEM;
-
-   

[PATCH 04/17] thermal: cpu_cooling: replace cool_dev with cdev

2017-03-15 Thread Viresh Kumar
Objects of "struct thermal_cooling_device" are named a bit
inconsistently. Lets use cdev everywhere.

Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7a19033d7f79..e2931c20c309 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -65,7 +65,7 @@ struct power_table {
  * struct cpufreq_cooling_device - data for cooling device with cpufreq
  * @id: unique integer value corresponding to each cpufreq_cooling_device
  * registered.
- * @cool_dev: thermal_cooling_device pointer to keep track of the
+ * @cdev: thermal_cooling_device pointer to keep track of the
  * registered cooling device.
  * @cpufreq_state: integer value representing the current state of cpufreq
  * cooling devices.
@@ -90,7 +90,7 @@ struct power_table {
  */
 struct cpufreq_cooling_device {
int id;
-   struct thermal_cooling_device *cool_dev;
+   struct thermal_cooling_device *cdev;
unsigned int cpufreq_state;
unsigned int clipped_freq;
unsigned int max_level;
@@ -243,7 +243,7 @@ static int build_dyn_power_table(struct 
cpufreq_cooling_device *cpufreq_dev,
for_each_cpu(cpu, _dev->allowed_cpus) {
dev = get_cpu_device(cpu);
if (!dev) {
-   dev_warn(_dev->cool_dev->device,
+   dev_warn(_dev->cdev->device,
 "No cpu device for cpu %d\n", cpu);
continue;
}
@@ -770,7 +770,7 @@ __cpufreq_cooling_register(struct device_node *np,
get_static_t plat_static_func)
 {
struct cpufreq_policy *policy;
-   struct thermal_cooling_device *cool_dev;
+   struct thermal_cooling_device *cdev;
struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH];
struct cpufreq_frequency_table *pos, *table;
@@ -786,20 +786,20 @@ __cpufreq_cooling_register(struct device_node *np,
policy = cpufreq_cpu_get(cpumask_first(temp_mask));
if (!policy) {
pr_debug("%s: CPUFreq policy not found\n", __func__);
-   cool_dev = ERR_PTR(-EPROBE_DEFER);
+   cdev = ERR_PTR(-EPROBE_DEFER);
goto free_cpumask;
}
 
table = policy->freq_table;
if (!table) {
pr_debug("%s: CPUFreq table not found\n", __func__);
-   cool_dev = ERR_PTR(-ENODEV);
+   cdev = ERR_PTR(-ENODEV);
goto put_policy;
}
 
cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL);
if (!cpufreq_dev) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto put_policy;
}
 
@@ -808,7 +808,7 @@ __cpufreq_cooling_register(struct device_node *np,
sizeof(*cpufreq_dev->time_in_idle),
GFP_KERNEL);
if (!cpufreq_dev->time_in_idle) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto free_cdev;
}
 
@@ -816,7 +816,7 @@ __cpufreq_cooling_register(struct device_node *np,
kcalloc(num_cpus, sizeof(*cpufreq_dev->time_in_idle_timestamp),
GFP_KERNEL);
if (!cpufreq_dev->time_in_idle_timestamp) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto free_time_in_idle;
}
 
@@ -827,7 +827,7 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
  cpufreq_dev->max_level, GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
-   cool_dev = ERR_PTR(-ENOMEM);
+   cdev = ERR_PTR(-ENOMEM);
goto free_time_in_idle_timestamp;
}
 
@@ -841,7 +841,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
ret = build_dyn_power_table(cpufreq_dev, capacitance);
if (ret) {
-   cool_dev = ERR_PTR(ret);
+   cdev = ERR_PTR(ret);
goto free_table;
}
 
@@ -852,7 +852,7 @@ __cpufreq_cooling_register(struct device_node *np,
 
ret = ida_simple_get(_ida, 0, 0, GFP_KERNEL);
if (ret < 0) {
-   cool_dev = ERR_PTR(ret);
+   cdev = ERR_PTR(ret);
goto free_power_table;
}
cpufreq_dev->id = ret;
@@ -872,13 +872,13 @@ __cpufreq_cooling_register(struct device_node *np,
snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
 cpufreq_dev->id);
 
-   cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
-   

[PATCH 01/17] thermal: cpu_cooling: Avoid accessing potentially freed structures

2017-03-15 Thread Viresh Kumar
After the lock is dropped, it is possible that the cpufreq_dev gets
freed before we call get_level() and that can cause kernel to crash.

Drop the lock after we are done using the structure.

Cc: 4.2+ 
Fixes: 02373d7c69b4 ("thermal: cpu_cooling: fix lockdep problems in 
cpu_cooling")
Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index c2525b585487..6fd258d62e47 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -155,8 +155,10 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, 
unsigned int freq)
mutex_lock(_list_lock);
list_for_each_entry(cpufreq_dev, _dev_list, node) {
if (cpumask_test_cpu(cpu, _dev->allowed_cpus)) {
+   unsigned long level = get_level(cpufreq_dev, freq);
+
mutex_unlock(_list_lock);
-   return get_level(cpufreq_dev, freq);
+   return level;
}
}
mutex_unlock(_list_lock);
-- 
2.7.1.410.g6faf27b



[PATCH 00/17] thermal: cpu_cooling: improve interaction with cpufreq core

2017-03-15 Thread Viresh Kumar
Hi Guys,

The cpu_cooling driver is designed to use CPU frequency scaling to avoid
high thermal states for a platform. But it wasn't glued really well with
cpufreq core.

This series tries to improve interactions between cpufreq core and
cpu_cooling driver and does some fixes/cleanups to the cpu_cooling
driver.

I am a bit confused about which tree this series should go through, PM
or thermal.

This series has dependency on few other patches which are already merged
in the PM [1] tree and thermal [2] tree. As this is 4.12 material, all
of this should go through only one tree to avoid conflicts.

I assume that one of Rafael and Rui have to drop the existing patch(es)
from their trees and let the other one apply all of these. I would let
you guys decide on that. Sorry for the trouble.

I have tested it on ARM 32 (exynos) and 64 bit (hikey) boards and have
pushed them for 0-day build bot and kernel CI testing as well. We should
know if something is broken with these.

@Javi: It would be good if you can give them a test, specially because
of your work on the "power" specific bits in the driver.

Pushed here as well:

git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git thermal/cooling

--
viresh

[1] https://marc.info/?l=linux-kernel=148946890403271=2
[2] https://marc.info/?l=linux-kernel=148644060126593=2

Viresh Kumar (17):
  thermal: cpu_cooling: Avoid accessing potentially freed structures
  thermal: cpu_cooling: rearrange globals
  thermal: cpu_cooling: Replace cpufreq_device with cpufreq_dev
  thermal: cpu_cooling: replace cool_dev with cdev
  thermal: cpu_cooling: remove cpufreq_cooling_get_level()
  thermal: cpu_cooling: get rid of a variable in cpufreq_set_cur_state()
  thermal: cpu_cooling: use cpufreq_policy to register cooling device
  cpufreq: create cpufreq_table_count_valid_entries()
  thermal: cpu_cooling: store cpufreq policy
  thermal: cpu_cooling: OPPs are registered for all CPUs
  thermal: cpu_cooling: get rid of 'allowed_cpus'
  thermal: cpu_cooling: merge frequency and power tables
  thermal: cpu_cooling: create structure for idle time stats
  thermal: cpu_cooling: get_level() can't fail
  thermal: cpu_cooling: don't store cpu_dev in cpufreq_dev
  thermal: cpu_cooling: 'freq' can't be zero in cpufreq_state2power()
  thermal: cpu_cooling: Rearrange struct cpufreq_cooling_device

 drivers/cpufreq/arm_big_little.c   |   2 +-
 drivers/cpufreq/cpufreq-dt.c   |   2 +-
 drivers/cpufreq/cpufreq_stats.c|  13 +-
 drivers/cpufreq/dbx500-cpufreq.c   |   2 +-
 drivers/cpufreq/mt8173-cpufreq.c   |   4 +-
 drivers/cpufreq/qoriq-cpufreq.c|   3 +-
 drivers/thermal/cpu_cooling.c  | 530 -
 drivers/thermal/imx_thermal.c  |  22 +-
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c |  22 +-
 include/linux/cpu_cooling.h|  32 +-
 include/linux/cpufreq.h|  14 +
 11 files changed, 272 insertions(+), 374 deletions(-)

-- 
2.7.1.410.g6faf27b



[PATCH 00/17] thermal: cpu_cooling: improve interaction with cpufreq core

2017-03-15 Thread Viresh Kumar
Hi Guys,

The cpu_cooling driver is designed to use CPU frequency scaling to avoid
high thermal states for a platform. But it wasn't glued really well with
cpufreq core.

This series tries to improve interactions between cpufreq core and
cpu_cooling driver and does some fixes/cleanups to the cpu_cooling
driver.

I am a bit confused about which tree this series should go through, PM
or thermal.

This series has dependency on few other patches which are already merged
in the PM [1] tree and thermal [2] tree. As this is 4.12 material, all
of this should go through only one tree to avoid conflicts.

I assume that one of Rafael and Rui have to drop the existing patch(es)
from their trees and let the other one apply all of these. I would let
you guys decide on that. Sorry for the trouble.

I have tested it on ARM 32 (exynos) and 64 bit (hikey) boards and have
pushed them for 0-day build bot and kernel CI testing as well. We should
know if something is broken with these.

@Javi: It would be good if you can give them a test, specially because
of your work on the "power" specific bits in the driver.

Pushed here as well:

git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git thermal/cooling

--
viresh

[1] https://marc.info/?l=linux-kernel=148946890403271=2
[2] https://marc.info/?l=linux-kernel=148644060126593=2

Viresh Kumar (17):
  thermal: cpu_cooling: Avoid accessing potentially freed structures
  thermal: cpu_cooling: rearrange globals
  thermal: cpu_cooling: Replace cpufreq_device with cpufreq_dev
  thermal: cpu_cooling: replace cool_dev with cdev
  thermal: cpu_cooling: remove cpufreq_cooling_get_level()
  thermal: cpu_cooling: get rid of a variable in cpufreq_set_cur_state()
  thermal: cpu_cooling: use cpufreq_policy to register cooling device
  cpufreq: create cpufreq_table_count_valid_entries()
  thermal: cpu_cooling: store cpufreq policy
  thermal: cpu_cooling: OPPs are registered for all CPUs
  thermal: cpu_cooling: get rid of 'allowed_cpus'
  thermal: cpu_cooling: merge frequency and power tables
  thermal: cpu_cooling: create structure for idle time stats
  thermal: cpu_cooling: get_level() can't fail
  thermal: cpu_cooling: don't store cpu_dev in cpufreq_dev
  thermal: cpu_cooling: 'freq' can't be zero in cpufreq_state2power()
  thermal: cpu_cooling: Rearrange struct cpufreq_cooling_device

 drivers/cpufreq/arm_big_little.c   |   2 +-
 drivers/cpufreq/cpufreq-dt.c   |   2 +-
 drivers/cpufreq/cpufreq_stats.c|  13 +-
 drivers/cpufreq/dbx500-cpufreq.c   |   2 +-
 drivers/cpufreq/mt8173-cpufreq.c   |   4 +-
 drivers/cpufreq/qoriq-cpufreq.c|   3 +-
 drivers/thermal/cpu_cooling.c  | 530 -
 drivers/thermal/imx_thermal.c  |  22 +-
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c |  22 +-
 include/linux/cpu_cooling.h|  32 +-
 include/linux/cpufreq.h|  14 +
 11 files changed, 272 insertions(+), 374 deletions(-)

-- 
2.7.1.410.g6faf27b



[PATCH 2/2] rpmsg: Introduce Qualcomm RPM glink driver

2017-03-15 Thread Bjorn Andersson
This introduces a basic driver for communicating over "native glink"
with the RPM found in Qualcomm platforms.

Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/Kconfig  |8 +
 drivers/rpmsg/Makefile |1 +
 drivers/rpmsg/qcom_glink_rpm.c | 1249 
 3 files changed, 1258 insertions(+)
 create mode 100644 drivers/rpmsg/qcom_glink_rpm.c

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index f12ac0b28263..c47a61dea8cd 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -13,6 +13,14 @@ config RPMSG_CHAR
  in /dev. They make it possible for user-space programs to send and
  receive rpmsg packets.
 
+config RPMSG_QCOM_GLINK_RPM
+   tristate "Qualcomm RPM Glink driver"
+   select RPMSG
+   help
+ Say y here to enable support for the GLINK RPM communication driver,
+ which serves as a channel for communication with the RPM in GLINK
+ enabled systems.
+
 config RPMSG_QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
depends on QCOM_SMEM
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index fae9a6d548fb..28cc19088cc0 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMSG)+= rpmsg_core.o
 obj-$(CONFIG_RPMSG_CHAR)   += rpmsg_char.o
+obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
 obj-$(CONFIG_RPMSG_QCOM_SMD)   += qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
new file mode 100644
index ..af97ae300bad
--- /dev/null
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -0,0 +1,1249 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rpmsg_internal.h"
+
+#define RPM_TOC_SIZE   256
+#define RPM_TOC_MAGIC  0x67727430 /* grt0 */
+#define RPM_TOC_MAX_ENTRIES((RPM_TOC_SIZE - sizeof(struct rpm_toc)) / \
+sizeof(struct rpm_toc_entry))
+
+#define RPM_TX_FIFO_ID 0x61703272 /* ap2r */
+#define RPM_RX_FIFO_ID 0x72326170 /* r2ap */
+
+#define GLINK_NAME_SIZE32
+
+#define RPM_GLINK_CID_MIN  1
+#define RPM_GLINK_CID_MAX  65536
+
+struct rpm_toc_entry {
+   __le32 id;
+   __le32 offset;
+   __le32 size;
+} __packed;
+
+struct rpm_toc {
+   __le32 magic;
+   __le32 count;
+
+   struct rpm_toc_entry entries[];
+} __packed;
+
+struct glink_msg {
+   __le16 cmd;
+   __le16 param1;
+   __le32 param2;
+   u8 data[];
+} __packed;
+
+struct glink_rpm_pipe {
+   void __iomem *tail;
+   void __iomem *head;
+
+   void __iomem *fifo;
+
+   size_t length;
+};
+
+/**
+ * struct glink_defer_cmd - deferred incoming control message
+ * @node:  list node
+ * @msg:   message header
+ * data:   payload of the message
+ *
+ * Copy of a received control message, to be added to @rx_queue and processed
+ * by @rx_work of @glink_rpm.
+ */
+struct glink_defer_cmd {
+   struct list_head node;
+
+   struct glink_msg msg;
+   u8 data[];
+};
+
+/**
+ * struct glink_rpm - driver context, relates to one remote subsystem
+ * @dev:   reference to the associated struct device
+ * @ipc_regmap:regmap for signaling remote
+ * @ipc_offset:offset in @ipc_regmap for signaling remote
+ * @ipc_bit:   bit in @ipc_offset for signaling remote
+ * @rx_pipe:   pipe object for receive FIFO
+ * @tx_pipe:   pipe object for transmit FIFO
+ * @irq:   IRQ for signaling incoming events
+ * @rx_work:   worker for handling received control messages
+ * @rx_lock:   protects the @rx_queue
+ * @rx_queue:  queue of received control messages to be processed in @rx_work
+ * @tx_lock:   synchronizes operations on the tx fifo
+ * @idr_lock:  synchronizes @lcids and @rcids modifications
+ * @lcids: idr of all channels with a known local channel id
+ * @rcids: idr of all channels with a known remote channel id
+ */
+struct glink_rpm {
+   struct device *dev;
+
+   struct regmap *ipc_regmap;
+   unsigned int ipc_offset;
+   unsigned int ipc_bit;
+
+   struct glink_rpm_pipe rx_pipe;
+   struct glink_rpm_pipe tx_pipe;
+
+   int irq;
+
+   struct work_struct rx_work;
+   spinlock_t rx_lock;
+   

[PATCH 2/2] rpmsg: Introduce Qualcomm RPM glink driver

2017-03-15 Thread Bjorn Andersson
This introduces a basic driver for communicating over "native glink"
with the RPM found in Qualcomm platforms.

Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/Kconfig  |8 +
 drivers/rpmsg/Makefile |1 +
 drivers/rpmsg/qcom_glink_rpm.c | 1249 
 3 files changed, 1258 insertions(+)
 create mode 100644 drivers/rpmsg/qcom_glink_rpm.c

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index f12ac0b28263..c47a61dea8cd 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -13,6 +13,14 @@ config RPMSG_CHAR
  in /dev. They make it possible for user-space programs to send and
  receive rpmsg packets.
 
+config RPMSG_QCOM_GLINK_RPM
+   tristate "Qualcomm RPM Glink driver"
+   select RPMSG
+   help
+ Say y here to enable support for the GLINK RPM communication driver,
+ which serves as a channel for communication with the RPM in GLINK
+ enabled systems.
+
 config RPMSG_QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
depends on QCOM_SMEM
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index fae9a6d548fb..28cc19088cc0 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMSG)+= rpmsg_core.o
 obj-$(CONFIG_RPMSG_CHAR)   += rpmsg_char.o
+obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
 obj-$(CONFIG_RPMSG_QCOM_SMD)   += qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
new file mode 100644
index ..af97ae300bad
--- /dev/null
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -0,0 +1,1249 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rpmsg_internal.h"
+
+#define RPM_TOC_SIZE   256
+#define RPM_TOC_MAGIC  0x67727430 /* grt0 */
+#define RPM_TOC_MAX_ENTRIES((RPM_TOC_SIZE - sizeof(struct rpm_toc)) / \
+sizeof(struct rpm_toc_entry))
+
+#define RPM_TX_FIFO_ID 0x61703272 /* ap2r */
+#define RPM_RX_FIFO_ID 0x72326170 /* r2ap */
+
+#define GLINK_NAME_SIZE32
+
+#define RPM_GLINK_CID_MIN  1
+#define RPM_GLINK_CID_MAX  65536
+
+struct rpm_toc_entry {
+   __le32 id;
+   __le32 offset;
+   __le32 size;
+} __packed;
+
+struct rpm_toc {
+   __le32 magic;
+   __le32 count;
+
+   struct rpm_toc_entry entries[];
+} __packed;
+
+struct glink_msg {
+   __le16 cmd;
+   __le16 param1;
+   __le32 param2;
+   u8 data[];
+} __packed;
+
+struct glink_rpm_pipe {
+   void __iomem *tail;
+   void __iomem *head;
+
+   void __iomem *fifo;
+
+   size_t length;
+};
+
+/**
+ * struct glink_defer_cmd - deferred incoming control message
+ * @node:  list node
+ * @msg:   message header
+ * data:   payload of the message
+ *
+ * Copy of a received control message, to be added to @rx_queue and processed
+ * by @rx_work of @glink_rpm.
+ */
+struct glink_defer_cmd {
+   struct list_head node;
+
+   struct glink_msg msg;
+   u8 data[];
+};
+
+/**
+ * struct glink_rpm - driver context, relates to one remote subsystem
+ * @dev:   reference to the associated struct device
+ * @ipc_regmap:regmap for signaling remote
+ * @ipc_offset:offset in @ipc_regmap for signaling remote
+ * @ipc_bit:   bit in @ipc_offset for signaling remote
+ * @rx_pipe:   pipe object for receive FIFO
+ * @tx_pipe:   pipe object for transmit FIFO
+ * @irq:   IRQ for signaling incoming events
+ * @rx_work:   worker for handling received control messages
+ * @rx_lock:   protects the @rx_queue
+ * @rx_queue:  queue of received control messages to be processed in @rx_work
+ * @tx_lock:   synchronizes operations on the tx fifo
+ * @idr_lock:  synchronizes @lcids and @rcids modifications
+ * @lcids: idr of all channels with a known local channel id
+ * @rcids: idr of all channels with a known remote channel id
+ */
+struct glink_rpm {
+   struct device *dev;
+
+   struct regmap *ipc_regmap;
+   unsigned int ipc_offset;
+   unsigned int ipc_bit;
+
+   struct glink_rpm_pipe rx_pipe;
+   struct glink_rpm_pipe tx_pipe;
+
+   int irq;
+
+   struct work_struct rx_work;
+   spinlock_t rx_lock;
+   struct list_head rx_queue;
+

[PATCH 1/2] soc: qcom: Add device tree binding for GLINK RPM

2017-03-15 Thread Bjorn Andersson
Add device tree binding documentation for the Qualcomm GLINK RPM, used
for communication with the Resource Power Management subsystem in
various Qualcomm SoCs.

Signed-off-by: Bjorn Andersson 
---
 .../devicetree/bindings/soc/qcom/qcom,glink.txt| 73 ++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt 
b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
new file mode 100644
index ..da92c4f787f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
@@ -0,0 +1,73 @@
+Qualcomm RPM GLINK binding
+
+This binding describes the Qualcomm RPM GLINK, a fifo based mechanism for
+communication with the Resource Power Management system on various Qualcomm
+platforms.
+
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,glink-rpm"
+
+- interrupts:
+   Usage: required
+   Value type: 
+   Definition: should specify the IRQ used by the remote processor to
+   signal this processor about communication related events
+
+- qcom,rpm-msg-ram:
+   Usage: required
+   Value type: 
+   Definition: handle to RPM message memory resource
+
+- qcom,ipc:
+   Usage: required
+   Value type: 
+   Definition: three entries specifying the outgoing ipc bit used for
+   signaling the remote processor:
+   - phandle to a syscon node representing the apcs registers
+   - u32 representing offset to the register within the syscon
+   - u32 representing the ipc bit within the register
+
+= GLINK DEVICES
+Each subnode of the GLINK node represent function tied to a virtual
+communication channel. The name of the nodes are not important. The properties
+of these nodes are defined by the individual bindings for the specific function
+- but must contain the following property:
+
+- qcom,glink-channels:
+   Usage: required
+   Value type: 
+   Definition: a list of channels tied to this function, used for matching
+   the function to a set of virtual channels
+
+= EXAMPLE
+The following example represents the GLINK RPM node on a MSM8996 device, with
+the function for the "rpm_request" channel defined, which is used for
+regualtors and root clocks.
+
+   apcs: syscon@f9011000 {
+   compatible = "syscon";
+   reg = <0xf9011000 0x1000>;
+   };
+
+   rpm_msg_ram: memory@68000 {
+   compatible = "qcom,rpm-msg-ram";
+   reg = <0x68000 0x6000>;
+   };
+
+rpm-glink {
+   compatible = "qcom,glink-rpm";
+
+   interrupts = ;
+
+   qcom,rpm-msg-ram = <_msg_ram>;
+   qcom,ipc = < 0x10 0>;
+
+   rpm-requests {
+   compatible = "qcom,rpm-msm8996";
+   qcom,glink-channels = "rpm_requests";
+
+   ...
+   };
+   };
-- 
2.12.0



[PATCH 1/2] soc: qcom: Add device tree binding for GLINK RPM

2017-03-15 Thread Bjorn Andersson
Add device tree binding documentation for the Qualcomm GLINK RPM, used
for communication with the Resource Power Management subsystem in
various Qualcomm SoCs.

Signed-off-by: Bjorn Andersson 
---
 .../devicetree/bindings/soc/qcom/qcom,glink.txt| 73 ++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt 
b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
new file mode 100644
index ..da92c4f787f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
@@ -0,0 +1,73 @@
+Qualcomm RPM GLINK binding
+
+This binding describes the Qualcomm RPM GLINK, a fifo based mechanism for
+communication with the Resource Power Management system on various Qualcomm
+platforms.
+
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,glink-rpm"
+
+- interrupts:
+   Usage: required
+   Value type: 
+   Definition: should specify the IRQ used by the remote processor to
+   signal this processor about communication related events
+
+- qcom,rpm-msg-ram:
+   Usage: required
+   Value type: 
+   Definition: handle to RPM message memory resource
+
+- qcom,ipc:
+   Usage: required
+   Value type: 
+   Definition: three entries specifying the outgoing ipc bit used for
+   signaling the remote processor:
+   - phandle to a syscon node representing the apcs registers
+   - u32 representing offset to the register within the syscon
+   - u32 representing the ipc bit within the register
+
+= GLINK DEVICES
+Each subnode of the GLINK node represent function tied to a virtual
+communication channel. The name of the nodes are not important. The properties
+of these nodes are defined by the individual bindings for the specific function
+- but must contain the following property:
+
+- qcom,glink-channels:
+   Usage: required
+   Value type: 
+   Definition: a list of channels tied to this function, used for matching
+   the function to a set of virtual channels
+
+= EXAMPLE
+The following example represents the GLINK RPM node on a MSM8996 device, with
+the function for the "rpm_request" channel defined, which is used for
+regualtors and root clocks.
+
+   apcs: syscon@f9011000 {
+   compatible = "syscon";
+   reg = <0xf9011000 0x1000>;
+   };
+
+   rpm_msg_ram: memory@68000 {
+   compatible = "qcom,rpm-msg-ram";
+   reg = <0x68000 0x6000>;
+   };
+
+rpm-glink {
+   compatible = "qcom,glink-rpm";
+
+   interrupts = ;
+
+   qcom,rpm-msg-ram = <_msg_ram>;
+   qcom,ipc = < 0x10 0>;
+
+   rpm-requests {
+   compatible = "qcom,rpm-msm8996";
+   qcom,glink-channels = "rpm_requests";
+
+   ...
+   };
+   };
-- 
2.12.0



Re: [PATCH] scsi: sr: fix oob access in get_capabilities

2017-03-15 Thread Kefeng Wang


On 2017/3/16 8:07, Martin K. Petersen wrote:
> Kefeng Wang  writes:
> 
> Kefeng,
> 
>> 'n = header_length + block_descriptor_length' could be greater than 512,
>> and will lead to oob access, so enlarge transfer buffer to fix it.
> 
> Can you share the output of sg_modes -p 0x2a /dev/srN for the offending
> drive?


root@localhost ~]# sg_modes -p 0x2a /dev/sr0
QEMU  QEMU DVD-ROM  0.15   peripheral_type: cd/dvd [0x5]
Mode parameter header from MODE SENSE(10):
Invalid block descriptor length=512, ignore
  Mode data length=36, medium type=0x70, specific param=0x00, longlba=0
  Block descriptor length=0
>> MM capabilities and mechanical status (obsolete), page_control: current
 00 2a 12 00 00 71 60 29 00  02 c2 00 02 02 00 02 c2
 10 00 00 00 00
Unexpectedly received extra mode page responses, ignore

note: the issue was found in guestos?  maybe some bugs exist in qemu?

Kefeng

> 
> This mode page is usually much smaller than 512 bytes (typically between
> 32 and 128 bytes).
> 



Re: [PATCH] scsi: sr: fix oob access in get_capabilities

2017-03-15 Thread Kefeng Wang


On 2017/3/16 8:07, Martin K. Petersen wrote:
> Kefeng Wang  writes:
> 
> Kefeng,
> 
>> 'n = header_length + block_descriptor_length' could be greater than 512,
>> and will lead to oob access, so enlarge transfer buffer to fix it.
> 
> Can you share the output of sg_modes -p 0x2a /dev/srN for the offending
> drive?


root@localhost ~]# sg_modes -p 0x2a /dev/sr0
QEMU  QEMU DVD-ROM  0.15   peripheral_type: cd/dvd [0x5]
Mode parameter header from MODE SENSE(10):
Invalid block descriptor length=512, ignore
  Mode data length=36, medium type=0x70, specific param=0x00, longlba=0
  Block descriptor length=0
>> MM capabilities and mechanical status (obsolete), page_control: current
 00 2a 12 00 00 71 60 29 00  02 c2 00 02 02 00 02 c2
 10 00 00 00 00
Unexpectedly received extra mode page responses, ignore

note: the issue was found in guestos?  maybe some bugs exist in qemu?

Kefeng

> 
> This mode page is usually much smaller than 512 bytes (typically between
> 32 and 128 bytes).
> 



[PATCH] rpmsg: Release rpmsg devices in backends

2017-03-15 Thread Bjorn Andersson
The rpmsg devices are allocated in the backends and as such must be
freed there as well.

Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_smd.c | 11 +++
 drivers/rpmsg/virtio_rpmsg_bus.c |  9 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index beaef5dd973e..a0a39a8821a3 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -969,6 +969,14 @@ static const struct rpmsg_endpoint_ops 
qcom_smd_endpoint_ops = {
.poll = qcom_smd_poll,
 };
 
+static void qcom_smd_release_device(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct qcom_smd_device *qsdev = to_smd_device(rpdev);
+
+   kfree(qsdev);
+}
+
 /*
  * Create a smd client device for channel that is being opened.
  */
@@ -998,6 +1006,7 @@ static int qcom_smd_create_device(struct qcom_smd_channel 
*channel)
 
rpdev->dev.of_node = qcom_smd_match_channel(edge->of_node, 
channel->name);
rpdev->dev.parent = >dev;
+   rpdev->dev.release = qcom_smd_release_device;
 
return rpmsg_register_device(rpdev);
 }
@@ -1013,6 +1022,8 @@ static int qcom_smd_create_chrdev(struct qcom_smd_edge 
*edge)
qsdev->edge = edge;
qsdev->rpdev.ops = _smd_device_ops;
qsdev->rpdev.dev.parent = >dev;
+   qsdev->rpdev.dev.release = qcom_smd_release_device;
+
return rpmsg_chrdev_register_device(>rpdev);
 }
 
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 5e66e081027e..7f8c5cc1c118 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -360,6 +360,14 @@ static const struct rpmsg_device_ops virtio_rpmsg_ops = {
.announce_destroy = virtio_rpmsg_announce_destroy,
 };
 
+static void virtio_rpmsg_release_device(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
+
+   kfree(vch);
+}
+
 /*
  * create an rpmsg channel using its name and address info.
  * this function will be used to create both static and dynamic
@@ -408,6 +416,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct 
virtproc_info *vrp,
strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
 
rpdev->dev.parent = >vdev->dev;
+   rpdev->dev.release = virtio_rpmsg_release_device;
ret = rpmsg_register_device(rpdev);
if (ret)
return NULL;
-- 
2.12.0



[PATCH] rpmsg: Release rpmsg devices in backends

2017-03-15 Thread Bjorn Andersson
The rpmsg devices are allocated in the backends and as such must be
freed there as well.

Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_smd.c | 11 +++
 drivers/rpmsg/virtio_rpmsg_bus.c |  9 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index beaef5dd973e..a0a39a8821a3 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -969,6 +969,14 @@ static const struct rpmsg_endpoint_ops 
qcom_smd_endpoint_ops = {
.poll = qcom_smd_poll,
 };
 
+static void qcom_smd_release_device(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct qcom_smd_device *qsdev = to_smd_device(rpdev);
+
+   kfree(qsdev);
+}
+
 /*
  * Create a smd client device for channel that is being opened.
  */
@@ -998,6 +1006,7 @@ static int qcom_smd_create_device(struct qcom_smd_channel 
*channel)
 
rpdev->dev.of_node = qcom_smd_match_channel(edge->of_node, 
channel->name);
rpdev->dev.parent = >dev;
+   rpdev->dev.release = qcom_smd_release_device;
 
return rpmsg_register_device(rpdev);
 }
@@ -1013,6 +1022,8 @@ static int qcom_smd_create_chrdev(struct qcom_smd_edge 
*edge)
qsdev->edge = edge;
qsdev->rpdev.ops = _smd_device_ops;
qsdev->rpdev.dev.parent = >dev;
+   qsdev->rpdev.dev.release = qcom_smd_release_device;
+
return rpmsg_chrdev_register_device(>rpdev);
 }
 
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 5e66e081027e..7f8c5cc1c118 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -360,6 +360,14 @@ static const struct rpmsg_device_ops virtio_rpmsg_ops = {
.announce_destroy = virtio_rpmsg_announce_destroy,
 };
 
+static void virtio_rpmsg_release_device(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
+
+   kfree(vch);
+}
+
 /*
  * create an rpmsg channel using its name and address info.
  * this function will be used to create both static and dynamic
@@ -408,6 +416,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct 
virtproc_info *vrp,
strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
 
rpdev->dev.parent = >vdev->dev;
+   rpdev->dev.release = virtio_rpmsg_release_device;
ret = rpmsg_register_device(rpdev);
if (ret)
return NULL;
-- 
2.12.0



[mmotm] "x86/atomic: move __arch_atomic_add_unless out of line" build error

2017-03-15 Thread Sergey Senozhatsky
Hello,

commit 4f86a82ff7df ("x86/atomic: move __arch_atomic_add_unless out of line")
moved __arch_atomic_add_unless() out atomic.h and new KASAN atomic
instrumentation [1] can't see it anymore


In file included from ./arch/x86/include/asm/atomic.h:257:0,
 from ./include/linux/atomic.h:4,
 from ./include/asm-generic/qspinlock_types.h:28,
 from ./arch/x86/include/asm/spinlock_types.h:26,
 from ./include/linux/spinlock_types.h:13,
 from kernel/bounds.c:13:
./include/asm-generic/atomic-instrumented.h: In function ‘__atomic_add_unless’:
./include/asm-generic/atomic-instrumented.h:70:9: error: implicit declaration 
of function ‘__arch_atomic_add_unless’ [-Werror=implicit-function-declaration]
  return __arch_atomic_add_unless(v, a, u);
 ^~~~


so we need a declaration of __arch_atomic_add_unless() in 
arch/x86/include/asm/atomic.h


[1] 
lkml.kernel.org/r/7e450175a324bf93c602909c711bc34715d8e8f2.1489519233.git.dvyu...@google.com

-ss


[mmotm] "x86/atomic: move __arch_atomic_add_unless out of line" build error

2017-03-15 Thread Sergey Senozhatsky
Hello,

commit 4f86a82ff7df ("x86/atomic: move __arch_atomic_add_unless out of line")
moved __arch_atomic_add_unless() out atomic.h and new KASAN atomic
instrumentation [1] can't see it anymore


In file included from ./arch/x86/include/asm/atomic.h:257:0,
 from ./include/linux/atomic.h:4,
 from ./include/asm-generic/qspinlock_types.h:28,
 from ./arch/x86/include/asm/spinlock_types.h:26,
 from ./include/linux/spinlock_types.h:13,
 from kernel/bounds.c:13:
./include/asm-generic/atomic-instrumented.h: In function ‘__atomic_add_unless’:
./include/asm-generic/atomic-instrumented.h:70:9: error: implicit declaration 
of function ‘__arch_atomic_add_unless’ [-Werror=implicit-function-declaration]
  return __arch_atomic_add_unless(v, a, u);
 ^~~~


so we need a declaration of __arch_atomic_add_unless() in 
arch/x86/include/asm/atomic.h


[1] 
lkml.kernel.org/r/7e450175a324bf93c602909c711bc34715d8e8f2.1489519233.git.dvyu...@google.com

-ss


Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Sergey Senozhatsky
Hello,


On (03/15/17 14:24), Minchan Kim wrote:
> There is no user for it. Remove it.
> 

there is one.

mm/rmap.c

try_to_unmap_one()
...
if (unlikely(PageSwapBacked(page) != PageSwapCache(page))) {
WARN_ON_ONCE(1);
ret = SWAP_FAIL;
page_vma_mapped_walk_done();
break;
}

-ss


Re: [PATCH v2 10/10] mm: remove SWAP_[SUCCESS|AGAIN|FAIL]

2017-03-15 Thread Sergey Senozhatsky
Hello,


On (03/15/17 14:24), Minchan Kim wrote:
> There is no user for it. Remove it.
> 

there is one.

mm/rmap.c

try_to_unmap_one()
...
if (unlikely(PageSwapBacked(page) != PageSwapCache(page))) {
WARN_ON_ONCE(1);
ret = SWAP_FAIL;
page_vma_mapped_walk_done();
break;
}

-ss


Re: [PATCH v3 4/7] macintosh: Only descend into directory when CONFIG_MACINTOSH_DRIVERS is set

2017-03-15 Thread Michael Ellerman
"Andrew F. Davis"  writes:

> When CONFIG_MACINTOSH_DRIVERS is not set make will still descend into the
> macintosh directory but nothing will be built. This produces unneeded
> build artifacts and messages in addition to slowing the build.
> Fix this here.
>
> Signed-off-by: Andrew F. Davis 
> ---
>  drivers/Makefile | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

LGTM.

Acked-by: Michael Ellerman 

cheersj


Re: [PATCH v3 4/7] macintosh: Only descend into directory when CONFIG_MACINTOSH_DRIVERS is set

2017-03-15 Thread Michael Ellerman
"Andrew F. Davis"  writes:

> When CONFIG_MACINTOSH_DRIVERS is not set make will still descend into the
> macintosh directory but nothing will be built. This produces unneeded
> build artifacts and messages in addition to slowing the build.
> Fix this here.
>
> Signed-off-by: Andrew F. Davis 
> ---
>  drivers/Makefile | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

LGTM.

Acked-by: Michael Ellerman 

cheersj


[PATCH v2] net: mvneta: support suspend and resume

2017-03-15 Thread Jane Li
Add basic support for handling suspend and resume.

Signed-off-by: Jane Li 
---
Since v1:
- add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume()

 drivers/net/ethernet/marvell/mvneta.c | 62 ---
 1 file changed, 58 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index 61dd446..250017b 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -431,6 +431,7 @@ struct mvneta_port {
/* Flags for special SoC configurations */
bool neta_armada3700;
u16 rx_offset_correction;
+   const struct mbus_dram_target_info *dram_target_info;
 };
 
 /* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, 
int phy_mode)
 /* Device initialization routine */
 static int mvneta_probe(struct platform_device *pdev)
 {
-   const struct mbus_dram_target_info *dram_target_info;
struct resource *res;
struct device_node *dn = pdev->dev.of_node;
struct device_node *phy_node;
@@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev)
 
pp->tx_csum_limit = tx_csum_limit;
 
-   dram_target_info = mv_mbus_dram_info();
+   pp->dram_target_info = mv_mbus_dram_info();
/* Armada3700 requires setting default configuration of Mbus
 * windows, however without using filled mbus_dram_target_info
 * structure.
 */
-   if (dram_target_info || pp->neta_armada3700)
-   mvneta_conf_mbus_windows(pp, dram_target_info);
+   if (pp->dram_target_info || pp->neta_armada3700)
+   mvneta_conf_mbus_windows(pp, pp->dram_target_info);
 
pp->tx_ring_size = MVNETA_MAX_TXD;
pp->rx_ring_size = MVNETA_MAX_RXD;
@@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev)
return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int mvneta_suspend(struct device *device)
+{
+   struct net_device *dev = dev_get_drvdata(device);
+   struct mvneta_port *pp = netdev_priv(dev);
+
+   if (netif_running(dev))
+   mvneta_stop(dev);
+   netif_device_detach(dev);
+   clk_disable_unprepare(pp->clk_bus);
+   clk_disable_unprepare(pp->clk);
+   return 0;
+}
+
+static int mvneta_resume(struct device *device)
+{
+   struct platform_device *pdev = to_platform_device(device);
+   struct net_device *dev = dev_get_drvdata(device);
+   struct mvneta_port *pp = netdev_priv(dev);
+   int err;
+
+   clk_prepare_enable(pp->clk);
+   clk_prepare_enable(pp->clk_bus);
+   if (pp->dram_target_info || pp->neta_armada3700)
+   mvneta_conf_mbus_windows(pp, pp->dram_target_info);
+   if (pp->bm_priv) {
+   err = mvneta_bm_port_init(pdev, pp);
+   if (err < 0) {
+   dev_info(>dev, "use SW buffer management\n");
+   pp->bm_priv = NULL;
+   }
+   }
+   mvneta_defaults_set(pp);
+   err = mvneta_port_power_up(pp, pp->phy_interface);
+   if (err < 0) {
+   dev_err(device, "can't power up port\n");
+   return err;
+   }
+
+   if (pp->use_inband_status)
+   mvneta_fixed_link_update(pp, dev->phydev);
+
+   netif_device_attach(dev);
+   if (netif_running(dev))
+   mvneta_open(dev);
+   return 0;
+}
+#endif
+
+static const struct dev_pm_ops mvneta_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume)
+};
+
 static const struct of_device_id mvneta_match[] = {
{ .compatible = "marvell,armada-370-neta" },
{ .compatible = "marvell,armada-xp-neta" },
@@ -4419,6 +4472,7 @@ static int mvneta_remove(struct platform_device *pdev)
.driver = {
.name = MVNETA_DRIVER_NAME,
.of_match_table = mvneta_match,
+   .pm = _pm_ops,
},
 };
 
-- 
1.9.1



[PATCH v2] net: mvneta: support suspend and resume

2017-03-15 Thread Jane Li
Add basic support for handling suspend and resume.

Signed-off-by: Jane Li 
---
Since v1:
- add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume()

 drivers/net/ethernet/marvell/mvneta.c | 62 ---
 1 file changed, 58 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index 61dd446..250017b 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -431,6 +431,7 @@ struct mvneta_port {
/* Flags for special SoC configurations */
bool neta_armada3700;
u16 rx_offset_correction;
+   const struct mbus_dram_target_info *dram_target_info;
 };
 
 /* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, 
int phy_mode)
 /* Device initialization routine */
 static int mvneta_probe(struct platform_device *pdev)
 {
-   const struct mbus_dram_target_info *dram_target_info;
struct resource *res;
struct device_node *dn = pdev->dev.of_node;
struct device_node *phy_node;
@@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev)
 
pp->tx_csum_limit = tx_csum_limit;
 
-   dram_target_info = mv_mbus_dram_info();
+   pp->dram_target_info = mv_mbus_dram_info();
/* Armada3700 requires setting default configuration of Mbus
 * windows, however without using filled mbus_dram_target_info
 * structure.
 */
-   if (dram_target_info || pp->neta_armada3700)
-   mvneta_conf_mbus_windows(pp, dram_target_info);
+   if (pp->dram_target_info || pp->neta_armada3700)
+   mvneta_conf_mbus_windows(pp, pp->dram_target_info);
 
pp->tx_ring_size = MVNETA_MAX_TXD;
pp->rx_ring_size = MVNETA_MAX_RXD;
@@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev)
return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int mvneta_suspend(struct device *device)
+{
+   struct net_device *dev = dev_get_drvdata(device);
+   struct mvneta_port *pp = netdev_priv(dev);
+
+   if (netif_running(dev))
+   mvneta_stop(dev);
+   netif_device_detach(dev);
+   clk_disable_unprepare(pp->clk_bus);
+   clk_disable_unprepare(pp->clk);
+   return 0;
+}
+
+static int mvneta_resume(struct device *device)
+{
+   struct platform_device *pdev = to_platform_device(device);
+   struct net_device *dev = dev_get_drvdata(device);
+   struct mvneta_port *pp = netdev_priv(dev);
+   int err;
+
+   clk_prepare_enable(pp->clk);
+   clk_prepare_enable(pp->clk_bus);
+   if (pp->dram_target_info || pp->neta_armada3700)
+   mvneta_conf_mbus_windows(pp, pp->dram_target_info);
+   if (pp->bm_priv) {
+   err = mvneta_bm_port_init(pdev, pp);
+   if (err < 0) {
+   dev_info(>dev, "use SW buffer management\n");
+   pp->bm_priv = NULL;
+   }
+   }
+   mvneta_defaults_set(pp);
+   err = mvneta_port_power_up(pp, pp->phy_interface);
+   if (err < 0) {
+   dev_err(device, "can't power up port\n");
+   return err;
+   }
+
+   if (pp->use_inband_status)
+   mvneta_fixed_link_update(pp, dev->phydev);
+
+   netif_device_attach(dev);
+   if (netif_running(dev))
+   mvneta_open(dev);
+   return 0;
+}
+#endif
+
+static const struct dev_pm_ops mvneta_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume)
+};
+
 static const struct of_device_id mvneta_match[] = {
{ .compatible = "marvell,armada-370-neta" },
{ .compatible = "marvell,armada-xp-neta" },
@@ -4419,6 +4472,7 @@ static int mvneta_remove(struct platform_device *pdev)
.driver = {
.name = MVNETA_DRIVER_NAME,
.of_match_table = mvneta_match,
+   .pm = _pm_ops,
},
 };
 
-- 
1.9.1



[PATCH] Staging: goldfish: use __func__ instead of embedded function names

2017-03-15 Thread Mohsin Shan
Embedded function names are less appropriate to use when
refactoring, can cause function renaming.  Prefer the use
of "%s", __func__ to embedded function names

Signed-off-by: Mohsin Shan 
---
 drivers/staging/goldfish/goldfish_nand.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/goldfish/goldfish_nand.c 
b/drivers/staging/goldfish/goldfish_nand.c
index 76d60ee..8f92ff4 100644
--- a/drivers/staging/goldfish/goldfish_nand.c
+++ b/drivers/staging/goldfish/goldfish_nand.c
@@ -114,8 +114,8 @@ static int goldfish_nand_erase(struct mtd_info *mtd, struct 
erase_info *instr)
len = len / mtd->writesize * (mtd->writesize + mtd->oobsize);
 
if (goldfish_nand_cmd(mtd, NAND_CMD_ERASE, ofs, len, NULL) != len) {
-   pr_err("goldfish_nand_erase: erase failed, start %llx, len %x, 
dev_size %llx, erase_size %x\n",
-  ofs, len, mtd->size, mtd->erasesize);
+   pr_err("%s: erase failed, start %llx, len %x, dev_size %llx, 
erase_size %x\n",
+  __func__, ofs, len, mtd->size, mtd->erasesize);
return -EIO;
}
 
@@ -125,8 +125,8 @@ static int goldfish_nand_erase(struct mtd_info *mtd, struct 
erase_info *instr)
return 0;
 
 invalid_arg:
-   pr_err("goldfish_nand_erase: invalid erase, start %llx, len %x, 
dev_size %llx, erase_size %x\n",
-  ofs, len, mtd->size, mtd->erasesize);
+   pr_err("%s: invalid erase, start %llx, len %x, dev_size %llx, 
erase_size %x\n",
+  __func__, ofs, len, mtd->size, mtd->erasesize);
return -EINVAL;
 }
 
@@ -254,8 +254,8 @@ static int goldfish_nand_block_isbad(struct mtd_info *mtd, 
loff_t ofs)
return goldfish_nand_cmd(mtd, NAND_CMD_BLOCK_BAD_GET, ofs, 0, NULL);
 
 invalid_arg:
-   pr_err("goldfish_nand_block_isbad: invalid arg, ofs %llx, dev_size 
%llx, write_size %x\n",
-  ofs, mtd->size, mtd->writesize);
+   pr_err("%s: invalid arg, ofs %llx, dev_size %llx, write_size %x\n",
+  __func__, ofs, mtd->size, mtd->writesize);
return -EINVAL;
 }
 
@@ -277,8 +277,8 @@ static int goldfish_nand_block_markbad(struct mtd_info 
*mtd, loff_t ofs)
return 0;
 
 invalid_arg:
-   pr_err("goldfish_nand_block_markbad: invalid arg, ofs %llx, dev_size 
%llx, write_size %x\n",
-  ofs, mtd->size, mtd->writesize);
+   pr_err("%s: invalid arg, ofs %llx, dev_size %llx, write_size %x\n",
+  __func__, ofs, mtd->size, mtd->writesize);
return -EINVAL;
 }
 
-- 
2.7.4



[PATCH] Staging: goldfish: use __func__ instead of embedded function names

2017-03-15 Thread Mohsin Shan
Embedded function names are less appropriate to use when
refactoring, can cause function renaming.  Prefer the use
of "%s", __func__ to embedded function names

Signed-off-by: Mohsin Shan 
---
 drivers/staging/goldfish/goldfish_nand.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/goldfish/goldfish_nand.c 
b/drivers/staging/goldfish/goldfish_nand.c
index 76d60ee..8f92ff4 100644
--- a/drivers/staging/goldfish/goldfish_nand.c
+++ b/drivers/staging/goldfish/goldfish_nand.c
@@ -114,8 +114,8 @@ static int goldfish_nand_erase(struct mtd_info *mtd, struct 
erase_info *instr)
len = len / mtd->writesize * (mtd->writesize + mtd->oobsize);
 
if (goldfish_nand_cmd(mtd, NAND_CMD_ERASE, ofs, len, NULL) != len) {
-   pr_err("goldfish_nand_erase: erase failed, start %llx, len %x, 
dev_size %llx, erase_size %x\n",
-  ofs, len, mtd->size, mtd->erasesize);
+   pr_err("%s: erase failed, start %llx, len %x, dev_size %llx, 
erase_size %x\n",
+  __func__, ofs, len, mtd->size, mtd->erasesize);
return -EIO;
}
 
@@ -125,8 +125,8 @@ static int goldfish_nand_erase(struct mtd_info *mtd, struct 
erase_info *instr)
return 0;
 
 invalid_arg:
-   pr_err("goldfish_nand_erase: invalid erase, start %llx, len %x, 
dev_size %llx, erase_size %x\n",
-  ofs, len, mtd->size, mtd->erasesize);
+   pr_err("%s: invalid erase, start %llx, len %x, dev_size %llx, 
erase_size %x\n",
+  __func__, ofs, len, mtd->size, mtd->erasesize);
return -EINVAL;
 }
 
@@ -254,8 +254,8 @@ static int goldfish_nand_block_isbad(struct mtd_info *mtd, 
loff_t ofs)
return goldfish_nand_cmd(mtd, NAND_CMD_BLOCK_BAD_GET, ofs, 0, NULL);
 
 invalid_arg:
-   pr_err("goldfish_nand_block_isbad: invalid arg, ofs %llx, dev_size 
%llx, write_size %x\n",
-  ofs, mtd->size, mtd->writesize);
+   pr_err("%s: invalid arg, ofs %llx, dev_size %llx, write_size %x\n",
+  __func__, ofs, mtd->size, mtd->writesize);
return -EINVAL;
 }
 
@@ -277,8 +277,8 @@ static int goldfish_nand_block_markbad(struct mtd_info 
*mtd, loff_t ofs)
return 0;
 
 invalid_arg:
-   pr_err("goldfish_nand_block_markbad: invalid arg, ofs %llx, dev_size 
%llx, write_size %x\n",
-  ofs, mtd->size, mtd->writesize);
+   pr_err("%s: invalid arg, ofs %llx, dev_size %llx, write_size %x\n",
+  __func__, ofs, mtd->size, mtd->writesize);
return -EINVAL;
 }
 
-- 
2.7.4



Re: [PATCH 1/2] reset: Add API to count number of reset available with device

2017-03-15 Thread Vivek Gautam
Hi Philipp,


On Wed, Mar 15, 2017 at 4:10 PM, Philipp Zabel  wrote:
> Hi Vivek,
>
> On Fri, 2017-03-10 at 20:10 +0530, Vivek Gautam wrote:
>> Hi Philipp,
>>
>>
>> On Wed, Feb 22, 2017 at 10:54 AM, Vivek Gautam
>>  wrote:
>> > Count number of reset phandles available with the device node
>> > to know the resets a given device has.
>> >
>> > Cc: Philipp Zabel 
>> > Signed-off-by: Vivek Gautam 
>> > ---
>>
>> Any thoughts on this change?
>> A small addition that seems useful.
>
> Sorry I missed this one earlier.
>
>> >
>> > Based on torvald's master branch.
>> >
>> >  include/linux/reset.h | 16 
>> >  1 file changed, 16 insertions(+)
>> >
>> > diff --git a/include/linux/reset.h b/include/linux/reset.h
>> > index 5daff15722d3..88f63a640153 100644
>> > --- a/include/linux/reset.h
>> > +++ b/include/linux/reset.h
>> > @@ -2,6 +2,7 @@
>> >  #define _LINUX_RESET_H_
>> >
>> >  #include 
>> > +#include 
>> >
>> >  struct reset_control;
>> >
>> > @@ -234,6 +235,21 @@ static inline struct reset_control 
>> > *of_reset_control_get_shared_by_index(
>> >  }
>> >
>> >  /**
>> > + * of_reset_control_get_count - Count number of resets available with a 
>> > device
>> > + * @node: device to be reset by the controller
>> > + */
>> > +static inline unsigned int of_reset_control_get_count(struct device_node 
>> > *node)
>> > +{
>> > +   int count;
>> > +
>> > +   count = of_count_phandle_with_args(node, "resets", "#reset-cells");
>> > +   if (count < 0)
>> > +   return 0;
>
> Please don't silently ignore errors. gpiod_count doesn't ignore errors
> either. tegra_powergate_of_resets in drivers/soc/tegra/pmc.c open codes
> this, too. This should be changed so it can be used there, too.

Sure, will change this. I can prepare a patch for tegra/pmc.c as well
using this.

Best regards
Vivek

>
> regards
> Philipp
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 1/2] reset: Add API to count number of reset available with device

2017-03-15 Thread Vivek Gautam
Hi Philipp,


On Wed, Mar 15, 2017 at 4:10 PM, Philipp Zabel  wrote:
> Hi Vivek,
>
> On Fri, 2017-03-10 at 20:10 +0530, Vivek Gautam wrote:
>> Hi Philipp,
>>
>>
>> On Wed, Feb 22, 2017 at 10:54 AM, Vivek Gautam
>>  wrote:
>> > Count number of reset phandles available with the device node
>> > to know the resets a given device has.
>> >
>> > Cc: Philipp Zabel 
>> > Signed-off-by: Vivek Gautam 
>> > ---
>>
>> Any thoughts on this change?
>> A small addition that seems useful.
>
> Sorry I missed this one earlier.
>
>> >
>> > Based on torvald's master branch.
>> >
>> >  include/linux/reset.h | 16 
>> >  1 file changed, 16 insertions(+)
>> >
>> > diff --git a/include/linux/reset.h b/include/linux/reset.h
>> > index 5daff15722d3..88f63a640153 100644
>> > --- a/include/linux/reset.h
>> > +++ b/include/linux/reset.h
>> > @@ -2,6 +2,7 @@
>> >  #define _LINUX_RESET_H_
>> >
>> >  #include 
>> > +#include 
>> >
>> >  struct reset_control;
>> >
>> > @@ -234,6 +235,21 @@ static inline struct reset_control 
>> > *of_reset_control_get_shared_by_index(
>> >  }
>> >
>> >  /**
>> > + * of_reset_control_get_count - Count number of resets available with a 
>> > device
>> > + * @node: device to be reset by the controller
>> > + */
>> > +static inline unsigned int of_reset_control_get_count(struct device_node 
>> > *node)
>> > +{
>> > +   int count;
>> > +
>> > +   count = of_count_phandle_with_args(node, "resets", "#reset-cells");
>> > +   if (count < 0)
>> > +   return 0;
>
> Please don't silently ignore errors. gpiod_count doesn't ignore errors
> either. tegra_powergate_of_resets in drivers/soc/tegra/pmc.c open codes
> this, too. This should be changed so it can be used there, too.

Sure, will change this. I can prepare a patch for tegra/pmc.c as well
using this.

Best regards
Vivek

>
> regards
> Philipp
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v2] net: mvneta: support suspend and resume

2017-03-15 Thread Jisheng Zhang
On Thu, 16 Mar 2017 11:19:10 +0800 Jane Li wrote:

> Add basic support for handling suspend and resume.
> 
> Signed-off-by: Jane Li 
> ---
> Since v1:
> - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume()
> 
>  drivers/net/ethernet/marvell/mvneta.c | 62 
> ---
>  1 file changed, 58 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
> b/drivers/net/ethernet/marvell/mvneta.c
> index 61dd446..250017b 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -431,6 +431,7 @@ struct mvneta_port {
>   /* Flags for special SoC configurations */
>   bool neta_armada3700;
>   u16 rx_offset_correction;
> + const struct mbus_dram_target_info *dram_target_info;
>  };
>  
>  /* The mvneta_tx_desc and mvneta_rx_desc structures describe the
> @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, 
> int phy_mode)
>  /* Device initialization routine */
>  static int mvneta_probe(struct platform_device *pdev)
>  {
> - const struct mbus_dram_target_info *dram_target_info;
>   struct resource *res;
>   struct device_node *dn = pdev->dev.of_node;
>   struct device_node *phy_node;
> @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev)
>  
>   pp->tx_csum_limit = tx_csum_limit;
>  
> - dram_target_info = mv_mbus_dram_info();
> + pp->dram_target_info = mv_mbus_dram_info();
>   /* Armada3700 requires setting default configuration of Mbus
>* windows, however without using filled mbus_dram_target_info
>* structure.
>*/
> - if (dram_target_info || pp->neta_armada3700)
> - mvneta_conf_mbus_windows(pp, dram_target_info);
> + if (pp->dram_target_info || pp->neta_armada3700)
> + mvneta_conf_mbus_windows(pp, pp->dram_target_info);
>  
>   pp->tx_ring_size = MVNETA_MAX_TXD;
>   pp->rx_ring_size = MVNETA_MAX_RXD;
> @@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev)
>   return 0;
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
> +static int mvneta_suspend(struct device *device)
> +{
> + struct net_device *dev = dev_get_drvdata(device);
> + struct mvneta_port *pp = netdev_priv(dev);
> +
> + if (netif_running(dev))
> + mvneta_stop(dev);
> + netif_device_detach(dev);
> + clk_disable_unprepare(pp->clk_bus);
> + clk_disable_unprepare(pp->clk);
> + return 0;
> +}
> +
> +static int mvneta_resume(struct device *device)
> +{
> + struct platform_device *pdev = to_platform_device(device);
> + struct net_device *dev = dev_get_drvdata(device);
> + struct mvneta_port *pp = netdev_priv(dev);
> + int err;
> +
> + clk_prepare_enable(pp->clk);
> + clk_prepare_enable(pp->clk_bus);
> + if (pp->dram_target_info || pp->neta_armada3700)
> + mvneta_conf_mbus_windows(pp, pp->dram_target_info);
> + if (pp->bm_priv) {
> + err = mvneta_bm_port_init(pdev, pp);
> + if (err < 0) {
> + dev_info(>dev, "use SW buffer management\n");
> + pp->bm_priv = NULL;
> + }
> + }
> + mvneta_defaults_set(pp);
> + err = mvneta_port_power_up(pp, pp->phy_interface);
> + if (err < 0) {
> + dev_err(device, "can't power up port\n");
> + return err;
> + }
> +
> + if (pp->use_inband_status)
> + mvneta_fixed_link_update(pp, dev->phydev);
> +
> + netif_device_attach(dev);
> + if (netif_running(dev))
> + mvneta_open(dev);
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops mvneta_pm_ops = {
> + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume)
> +};

we could make use of SIMPLE_DEV_PM_OPS to simplify the code

Thanks


Re: [PATCH v2] net: mvneta: support suspend and resume

2017-03-15 Thread Jisheng Zhang
On Thu, 16 Mar 2017 11:19:10 +0800 Jane Li wrote:

> Add basic support for handling suspend and resume.
> 
> Signed-off-by: Jane Li 
> ---
> Since v1:
> - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume()
> 
>  drivers/net/ethernet/marvell/mvneta.c | 62 
> ---
>  1 file changed, 58 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
> b/drivers/net/ethernet/marvell/mvneta.c
> index 61dd446..250017b 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -431,6 +431,7 @@ struct mvneta_port {
>   /* Flags for special SoC configurations */
>   bool neta_armada3700;
>   u16 rx_offset_correction;
> + const struct mbus_dram_target_info *dram_target_info;
>  };
>  
>  /* The mvneta_tx_desc and mvneta_rx_desc structures describe the
> @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, 
> int phy_mode)
>  /* Device initialization routine */
>  static int mvneta_probe(struct platform_device *pdev)
>  {
> - const struct mbus_dram_target_info *dram_target_info;
>   struct resource *res;
>   struct device_node *dn = pdev->dev.of_node;
>   struct device_node *phy_node;
> @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev)
>  
>   pp->tx_csum_limit = tx_csum_limit;
>  
> - dram_target_info = mv_mbus_dram_info();
> + pp->dram_target_info = mv_mbus_dram_info();
>   /* Armada3700 requires setting default configuration of Mbus
>* windows, however without using filled mbus_dram_target_info
>* structure.
>*/
> - if (dram_target_info || pp->neta_armada3700)
> - mvneta_conf_mbus_windows(pp, dram_target_info);
> + if (pp->dram_target_info || pp->neta_armada3700)
> + mvneta_conf_mbus_windows(pp, pp->dram_target_info);
>  
>   pp->tx_ring_size = MVNETA_MAX_TXD;
>   pp->rx_ring_size = MVNETA_MAX_RXD;
> @@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev)
>   return 0;
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
> +static int mvneta_suspend(struct device *device)
> +{
> + struct net_device *dev = dev_get_drvdata(device);
> + struct mvneta_port *pp = netdev_priv(dev);
> +
> + if (netif_running(dev))
> + mvneta_stop(dev);
> + netif_device_detach(dev);
> + clk_disable_unprepare(pp->clk_bus);
> + clk_disable_unprepare(pp->clk);
> + return 0;
> +}
> +
> +static int mvneta_resume(struct device *device)
> +{
> + struct platform_device *pdev = to_platform_device(device);
> + struct net_device *dev = dev_get_drvdata(device);
> + struct mvneta_port *pp = netdev_priv(dev);
> + int err;
> +
> + clk_prepare_enable(pp->clk);
> + clk_prepare_enable(pp->clk_bus);
> + if (pp->dram_target_info || pp->neta_armada3700)
> + mvneta_conf_mbus_windows(pp, pp->dram_target_info);
> + if (pp->bm_priv) {
> + err = mvneta_bm_port_init(pdev, pp);
> + if (err < 0) {
> + dev_info(>dev, "use SW buffer management\n");
> + pp->bm_priv = NULL;
> + }
> + }
> + mvneta_defaults_set(pp);
> + err = mvneta_port_power_up(pp, pp->phy_interface);
> + if (err < 0) {
> + dev_err(device, "can't power up port\n");
> + return err;
> + }
> +
> + if (pp->use_inband_status)
> + mvneta_fixed_link_update(pp, dev->phydev);
> +
> + netif_device_attach(dev);
> + if (netif_running(dev))
> + mvneta_open(dev);
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops mvneta_pm_ops = {
> + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume)
> +};

we could make use of SIMPLE_DEV_PM_OPS to simplify the code

Thanks


Re: [PATCH v5 2/3] soc/imx: Add GPCv2 power gating driver

2017-03-15 Thread Shawn Guo
On Tue, Mar 14, 2017 at 08:05:39AM -0700, Andrey Smirnov wrote:
> Add code allowing for control of various power domains managed by GPCv2
> IP block found in i.MX7 series of SoCs. Power domains covered by this
> patch are:
> 
> - PCIE PHY
> - MIPI PHY
> - USB HSIC PHY
> - USB OTG1/2 PHY
> 
> Support for any other power domain controlled by GPC is not present, and
> can be added at some later point.
> 
> Testing of this code was done against a PCIe driver.
> 
> Cc: yurov...@gmail.com
> Cc: Lucas Stach 
> Cc: Fabio Estevam 
> Cc: linux-arm-ker...@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Andrey Smirnov 
> ---
>  drivers/soc/Kconfig  |   1 +
>  drivers/soc/imx/Kconfig  |   9 ++
>  drivers/soc/imx/Makefile |   1 +
>  drivers/soc/imx/gpcv2.c  | 387 
> +++
>  4 files changed, 398 insertions(+)
>  create mode 100644 drivers/soc/imx/Kconfig
>  create mode 100644 drivers/soc/imx/gpcv2.c
> 
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index f31bceb..55a4eb8 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
>  
>  source "drivers/soc/bcm/Kconfig"
>  source "drivers/soc/fsl/Kconfig"
> +source "drivers/soc/imx/Kconfig"
>  source "drivers/soc/mediatek/Kconfig"
>  source "drivers/soc/qcom/Kconfig"
>  source "drivers/soc/rockchip/Kconfig"
> diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
> new file mode 100644
> index 000..9c84eb0
> --- /dev/null
> +++ b/drivers/soc/imx/Kconfig
> @@ -0,0 +1,9 @@
> +menu "i.MX SoC drivers"
> +
> +config IMX7_PM_DOMAINS
> + bool "i.MX7 PM domains"
> + select PM_GENERIC_DOMAINS
> + depends on SOC_IMX7D || (COMPILE_TEST && OF)

Can we do something like below to save the patch #3?

default y if SOC_IMX7D

> +
> +endmenu
> +
> diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
> index 35861f5..5b6e396 100644
> --- a/drivers/soc/imx/Makefile
> +++ b/drivers/soc/imx/Makefile
> @@ -1 +1,2 @@
>  obj-y += gpc.o
> +obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
> diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
> new file mode 100644
> index 000..7d52141
> --- /dev/null
> +++ b/drivers/soc/imx/gpcv2.c
> @@ -0,0 +1,387 @@
> +/*
> + * Copyright 2017 Impinj, Inc
> + * Author: Andrey Smirnov 
> + *
> + * Based on the code of analogus driver:
> + *
> + * Copyright 2015-2017 Pengutronix, Lucas Stach 
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define GPC_PGC_CPU_MAPPING  0xec
> +#define USB_HSIC_PHY_A7_DOMAIN   BIT(6)
> +#define USB_OTG2_PHY_A7_DOMAIN   BIT(5)
> +#define USB_OTG1_PHY_A7_DOMAIN   BIT(4)
> +#define PCIE_PHY_A7_DOMAIN   BIT(3)
> +#define MIPI_PHY_A7_DOMAIN   BIT(2)
> +
> +#define GPC_PU_PGC_SW_PUP_REQ0xf8
> +#define GPC_PU_PGC_SW_PDN_REQ0x104
> +#define USB_HSIC_PHY_SW_Pxx_REQ  BIT(4)
> +#define USB_OTG2_PHY_SW_Pxx_REQ  BIT(3)
> +#define USB_OTG1_PHY_SW_Pxx_REQ  BIT(2)
> +#define PCIE_PHY_SW_Pxx_REQ  BIT(1)
> +#define MIPI_PHY_SW_Pxx_REQ  BIT(0)
> +
> +#define GPC_MAX_REGISTER 0x1000
> +
> +#define GPC_PGC_nCTRL_PCRBIT(0)
> +
> +struct imx7_pgc_domain {
> + struct generic_pm_domain genpd;
> + struct regmap *regmap;
> + struct regulator *regulator;
> +
> + unsigned int pgc_nctrl;
> +
> + const struct {
> + u32 pxx;
> + u32 map;
> + } bits;
> +
> + const int voltage;
> + struct device *dev;
> +};
> +
> +static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
> +   bool on)
> +{
> + int ret = 0;
> + unsigned long deadline;
> + struct imx7_pgc_domain *domain = container_of(genpd,
> +   struct imx7_pgc_domain,
> +   genpd);
> + unsigned int offset = on ?
> + GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
> +
> + const bool enable_power_control = domain->pgc_nctrl && !on;
> + const bool has_regulator = !IS_ERR(domain->regulator);

Again, reverse tree for variable declaration section, and drop the
newline in middle of it please.

Shawn

> +
> + regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
> +domain->bits.map, domain->bits.map);
> +
> + if (has_regulator && on) {
> + ret = regulator_enable(domain->regulator);

Re: [PATCH 1/7] trace: Move trace_seq_overflowed out of line

2017-03-15 Thread Steven Rostedt
On Wed, 15 Mar 2017 23:20:30 -0400
Steven Rostedt  wrote:

> > It is used in lots of places outside trace_handle_return, so that would
> > give far less savings.  

Actually, I think you'll probably have *more* savings inlining
trace_handle_return() than trace_seq_has_overflowed(). Why?

Think about it now before looking at the answer below.

> > include/linux/trace_events.h:143:   return trace_seq_has_overflowed(s) 
> > ?  
> 
> Every thing below is negligible. The above which is called in
> trace_handle_return() is your problem.
> 
> Let me explain it to you.
> 
> The above is part of the TRACE_EVENT() logic. It is duplicated for
> *every* tracepoint in the system.
> 
> Looking at a current kernel:
> 
>  # ls /debug/tracing/events/*/*/enable | wc -l
> 1267
> 
> There's 1267 events. That means the function trace_handle_return() is
> called 1267 times! THAT IS THE PROBLEM
> 
> Look at include/trace/trace_events.h for
> 
>   trace_raw_output_##call()
> 
> That's the macro that creates over a thousand functions calling
> trace_handle_return().
> 

trace_handle_return() is called 1267 times. If you out of line that
function, not only do you save the compares, you also save the
condition too! That could be a jump as well.

static inline enum print_line_t trace_handle_return(struct trace_seq *s)
{
return trace_seq_has_overflowed(s) ?
TRACE_TYPE_PARTIAL_LINE : TRACE_TYPE_HANDLED;
}

The above is called 1267 times. If you move out of line
trace_seq_has_overflowed() you only saved the

s->full || s->seq->len > s->seq->size

part from being duplicated.

But if you out of line trace_handle_return, you move out

s->full || s->seq->len > s->seq->size ?
TRACE_TYPE_PARTIAL_LINE :
TRACE_TYPE-HANDLED

1267 times as well.

Try it. It may surprise you.

-- Steve



Re: [PATCH v5 2/3] soc/imx: Add GPCv2 power gating driver

2017-03-15 Thread Shawn Guo
On Tue, Mar 14, 2017 at 08:05:39AM -0700, Andrey Smirnov wrote:
> Add code allowing for control of various power domains managed by GPCv2
> IP block found in i.MX7 series of SoCs. Power domains covered by this
> patch are:
> 
> - PCIE PHY
> - MIPI PHY
> - USB HSIC PHY
> - USB OTG1/2 PHY
> 
> Support for any other power domain controlled by GPC is not present, and
> can be added at some later point.
> 
> Testing of this code was done against a PCIe driver.
> 
> Cc: yurov...@gmail.com
> Cc: Lucas Stach 
> Cc: Fabio Estevam 
> Cc: linux-arm-ker...@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Andrey Smirnov 
> ---
>  drivers/soc/Kconfig  |   1 +
>  drivers/soc/imx/Kconfig  |   9 ++
>  drivers/soc/imx/Makefile |   1 +
>  drivers/soc/imx/gpcv2.c  | 387 
> +++
>  4 files changed, 398 insertions(+)
>  create mode 100644 drivers/soc/imx/Kconfig
>  create mode 100644 drivers/soc/imx/gpcv2.c
> 
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index f31bceb..55a4eb8 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
>  
>  source "drivers/soc/bcm/Kconfig"
>  source "drivers/soc/fsl/Kconfig"
> +source "drivers/soc/imx/Kconfig"
>  source "drivers/soc/mediatek/Kconfig"
>  source "drivers/soc/qcom/Kconfig"
>  source "drivers/soc/rockchip/Kconfig"
> diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
> new file mode 100644
> index 000..9c84eb0
> --- /dev/null
> +++ b/drivers/soc/imx/Kconfig
> @@ -0,0 +1,9 @@
> +menu "i.MX SoC drivers"
> +
> +config IMX7_PM_DOMAINS
> + bool "i.MX7 PM domains"
> + select PM_GENERIC_DOMAINS
> + depends on SOC_IMX7D || (COMPILE_TEST && OF)

Can we do something like below to save the patch #3?

default y if SOC_IMX7D

> +
> +endmenu
> +
> diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
> index 35861f5..5b6e396 100644
> --- a/drivers/soc/imx/Makefile
> +++ b/drivers/soc/imx/Makefile
> @@ -1 +1,2 @@
>  obj-y += gpc.o
> +obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
> diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
> new file mode 100644
> index 000..7d52141
> --- /dev/null
> +++ b/drivers/soc/imx/gpcv2.c
> @@ -0,0 +1,387 @@
> +/*
> + * Copyright 2017 Impinj, Inc
> + * Author: Andrey Smirnov 
> + *
> + * Based on the code of analogus driver:
> + *
> + * Copyright 2015-2017 Pengutronix, Lucas Stach 
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define GPC_PGC_CPU_MAPPING  0xec
> +#define USB_HSIC_PHY_A7_DOMAIN   BIT(6)
> +#define USB_OTG2_PHY_A7_DOMAIN   BIT(5)
> +#define USB_OTG1_PHY_A7_DOMAIN   BIT(4)
> +#define PCIE_PHY_A7_DOMAIN   BIT(3)
> +#define MIPI_PHY_A7_DOMAIN   BIT(2)
> +
> +#define GPC_PU_PGC_SW_PUP_REQ0xf8
> +#define GPC_PU_PGC_SW_PDN_REQ0x104
> +#define USB_HSIC_PHY_SW_Pxx_REQ  BIT(4)
> +#define USB_OTG2_PHY_SW_Pxx_REQ  BIT(3)
> +#define USB_OTG1_PHY_SW_Pxx_REQ  BIT(2)
> +#define PCIE_PHY_SW_Pxx_REQ  BIT(1)
> +#define MIPI_PHY_SW_Pxx_REQ  BIT(0)
> +
> +#define GPC_MAX_REGISTER 0x1000
> +
> +#define GPC_PGC_nCTRL_PCRBIT(0)
> +
> +struct imx7_pgc_domain {
> + struct generic_pm_domain genpd;
> + struct regmap *regmap;
> + struct regulator *regulator;
> +
> + unsigned int pgc_nctrl;
> +
> + const struct {
> + u32 pxx;
> + u32 map;
> + } bits;
> +
> + const int voltage;
> + struct device *dev;
> +};
> +
> +static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
> +   bool on)
> +{
> + int ret = 0;
> + unsigned long deadline;
> + struct imx7_pgc_domain *domain = container_of(genpd,
> +   struct imx7_pgc_domain,
> +   genpd);
> + unsigned int offset = on ?
> + GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
> +
> + const bool enable_power_control = domain->pgc_nctrl && !on;
> + const bool has_regulator = !IS_ERR(domain->regulator);

Again, reverse tree for variable declaration section, and drop the
newline in middle of it please.

Shawn

> +
> + regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
> +domain->bits.map, domain->bits.map);
> +
> + if (has_regulator && on) {
> + ret = regulator_enable(domain->regulator);
> + if (ret) {
> + dev_err(domain->dev, "failed to enable regulator\n");
> +   

Re: [PATCH 1/7] trace: Move trace_seq_overflowed out of line

2017-03-15 Thread Steven Rostedt
On Wed, 15 Mar 2017 23:20:30 -0400
Steven Rostedt  wrote:

> > It is used in lots of places outside trace_handle_return, so that would
> > give far less savings.  

Actually, I think you'll probably have *more* savings inlining
trace_handle_return() than trace_seq_has_overflowed(). Why?

Think about it now before looking at the answer below.

> > include/linux/trace_events.h:143:   return trace_seq_has_overflowed(s) 
> > ?  
> 
> Every thing below is negligible. The above which is called in
> trace_handle_return() is your problem.
> 
> Let me explain it to you.
> 
> The above is part of the TRACE_EVENT() logic. It is duplicated for
> *every* tracepoint in the system.
> 
> Looking at a current kernel:
> 
>  # ls /debug/tracing/events/*/*/enable | wc -l
> 1267
> 
> There's 1267 events. That means the function trace_handle_return() is
> called 1267 times! THAT IS THE PROBLEM
> 
> Look at include/trace/trace_events.h for
> 
>   trace_raw_output_##call()
> 
> That's the macro that creates over a thousand functions calling
> trace_handle_return().
> 

trace_handle_return() is called 1267 times. If you out of line that
function, not only do you save the compares, you also save the
condition too! That could be a jump as well.

static inline enum print_line_t trace_handle_return(struct trace_seq *s)
{
return trace_seq_has_overflowed(s) ?
TRACE_TYPE_PARTIAL_LINE : TRACE_TYPE_HANDLED;
}

The above is called 1267 times. If you move out of line
trace_seq_has_overflowed() you only saved the

s->full || s->seq->len > s->seq->size

part from being duplicated.

But if you out of line trace_handle_return, you move out

s->full || s->seq->len > s->seq->size ?
TRACE_TYPE_PARTIAL_LINE :
TRACE_TYPE-HANDLED

1267 times as well.

Try it. It may surprise you.

-- Steve



[PATCH v1 1/1] platform/x86: intel_pmc_ipc: fix io mem mapping size

2017-03-15 Thread Kuppuswamy Sathyanarayanan
Mapping entire GCR mem region in this driver creates
mem region request conflict in sub devices that depend
on PMC. This creates driver probe failure in devices like
iTC0_wdt and telemetry device.

Currently this driver only need memory mapping for
s0ix counter registers. So this patch fixes this issue
by requesting memory mapping for only the s0ix counter mem
region.

Signed-off-by: Kuppuswamy Sathyanarayanan 

---
 drivers/platform/x86/intel_pmc_ipc.c | 59 +---
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/platform/x86/intel_pmc_ipc.c 
b/drivers/platform/x86/intel_pmc_ipc.c
index 0651d47..2b8a090 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -58,8 +58,8 @@
 #define IPC_READ_BUFFER0x90
 
 /* PMC Global Control Registers */
-#define GCR_TELEM_DEEP_S0IX_OFFSET 0x1078
-#define GCR_TELEM_SHLW_S0IX_OFFSET 0x1080
+#define GCR_TELEM_DEEP_S0IX_OFFSET 0x0
+#define GCR_TELEM_SHLW_S0IX_OFFSET 0x8
 
 /* Residency with clock rate at 19.2MHz to usecs */
 #define S0IX_RESIDENCY_IN_USECS(d, s)  \
@@ -84,6 +84,8 @@
 #define PLAT_RESOURCE_IPC_SIZE 0x1000
 #define PLAT_RESOURCE_GCR_OFFSET   0x1008
 #define PLAT_RESOURCE_GCR_SIZE 0x1000
+#define PLAT_RESOURCE_GCR_S0IX_OFFSET  0x1078
+#define PLAT_RESOURCE_GCR_S0IX_SIZE12
 #define PLAT_RESOURCE_BIOS_DATA_INDEX  1
 #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
 #define PLAT_RESOURCE_TELEM_SSRAM_INDEX3
@@ -130,6 +132,11 @@ static struct intel_pmc_ipc_dev {
int gcr_size;
bool has_gcr_regs;
 
+   /* s0ix counters */
+   resource_size_t gcr_s0ix_start;
+   int gcr_s0ix_size;
+   void __iomem *gcr_s0ix_base;
+
/* punit */
struct platform_device *punit_dev;
 
@@ -194,9 +201,9 @@ static inline u32 ipc_data_readl(u32 offset)
return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
 }
 
-static inline u64 gcr_data_readq(u32 offset)
+static inline u64 gcr_s0ix_data_readq(u32 offset)
 {
-   return readq(ipcdev.ipc_base + offset);
+   return readq(ipcdev.gcr_s0ix_base + offset);
 }
 
 static int intel_pmc_ipc_check_status(void)
@@ -732,7 +739,7 @@ static int ipc_plat_get_res(struct platform_device *pdev)
dev_err(>dev, "Failed to get ipc resource\n");
return -ENXIO;
}
-   size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE;
+   size = PLAT_RESOURCE_IPC_SIZE;
 
if (!request_mem_region(res->start, size, pdev->name)) {
dev_err(>dev, "Failed to request ipc resource\n");
@@ -748,8 +755,36 @@ static int ipc_plat_get_res(struct platform_device *pdev)
 
ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET;
ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
+
dev_info(>dev, "ipc res: %pR\n", res);
 
+   /* request s0ix counter reg memory */
+   ipcdev.gcr_s0ix_start = res->start + PLAT_RESOURCE_GCR_S0IX_OFFSET;
+   ipcdev.gcr_s0ix_size = PLAT_RESOURCE_GCR_S0IX_SIZE;
+
+   if (!request_mem_region(ipcdev.gcr_s0ix_start, ipcdev.gcr_s0ix_size,
+   "ipc_gcr_s0ix")) {
+   dev_err(>dev, "Failed to request s0ix mem region\n");
+   iounmap(ipcdev.ipc_base);
+   release_mem_region(res->start, size);
+   return -EBUSY;
+   }
+
+   addr = ioremap_nocache(ipcdev.gcr_s0ix_start, ipcdev.gcr_s0ix_size);
+   if (!addr) {
+   dev_err(>dev, "s0ix I/O memory remapping failed\n");
+   release_mem_region(ipcdev.gcr_s0ix_start, ipcdev.gcr_s0ix_size);
+   iounmap(ipcdev.ipc_base);
+   release_mem_region(res->start, size);
+   return -ENOMEM;
+   }
+
+   ipcdev.gcr_s0ix_base = addr;
+
+   dev_info(>dev, "s0ix mem region 0x%llx-0x%llx\n",
+ipcdev.gcr_s0ix_start,
+(ipcdev.gcr_s0ix_start + ipcdev.gcr_s0ix_size - 1));
+
ipcdev.telem_res_inval = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_TELEM_SSRAM_INDEX);
@@ -782,8 +817,8 @@ int intel_pmc_s0ix_counter_read(u64 *data)
if (!ipcdev.has_gcr_regs)
return -EACCES;
 
-   deep = gcr_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET);
-   shlw = gcr_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET);
+   deep = gcr_s0ix_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET);
+   shlw = gcr_s0ix_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET);
 
*data = S0IX_RESIDENCY_IN_USECS(deep, shlw);
 
@@ -851,12 +886,13 @@ static int ipc_plat_probe(struct platform_device *pdev)
platform_device_unregister(ipcdev.telemetry_dev);
 err_device:
iounmap(ipcdev.ipc_base);
+   iounmap(ipcdev.gcr_s0ix_base);
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_IPC_INDEX);

[PATCH v1 1/1] platform/x86: intel_pmc_ipc: fix io mem mapping size

2017-03-15 Thread Kuppuswamy Sathyanarayanan
Mapping entire GCR mem region in this driver creates
mem region request conflict in sub devices that depend
on PMC. This creates driver probe failure in devices like
iTC0_wdt and telemetry device.

Currently this driver only need memory mapping for
s0ix counter registers. So this patch fixes this issue
by requesting memory mapping for only the s0ix counter mem
region.

Signed-off-by: Kuppuswamy Sathyanarayanan 

---
 drivers/platform/x86/intel_pmc_ipc.c | 59 +---
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/platform/x86/intel_pmc_ipc.c 
b/drivers/platform/x86/intel_pmc_ipc.c
index 0651d47..2b8a090 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -58,8 +58,8 @@
 #define IPC_READ_BUFFER0x90
 
 /* PMC Global Control Registers */
-#define GCR_TELEM_DEEP_S0IX_OFFSET 0x1078
-#define GCR_TELEM_SHLW_S0IX_OFFSET 0x1080
+#define GCR_TELEM_DEEP_S0IX_OFFSET 0x0
+#define GCR_TELEM_SHLW_S0IX_OFFSET 0x8
 
 /* Residency with clock rate at 19.2MHz to usecs */
 #define S0IX_RESIDENCY_IN_USECS(d, s)  \
@@ -84,6 +84,8 @@
 #define PLAT_RESOURCE_IPC_SIZE 0x1000
 #define PLAT_RESOURCE_GCR_OFFSET   0x1008
 #define PLAT_RESOURCE_GCR_SIZE 0x1000
+#define PLAT_RESOURCE_GCR_S0IX_OFFSET  0x1078
+#define PLAT_RESOURCE_GCR_S0IX_SIZE12
 #define PLAT_RESOURCE_BIOS_DATA_INDEX  1
 #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
 #define PLAT_RESOURCE_TELEM_SSRAM_INDEX3
@@ -130,6 +132,11 @@ static struct intel_pmc_ipc_dev {
int gcr_size;
bool has_gcr_regs;
 
+   /* s0ix counters */
+   resource_size_t gcr_s0ix_start;
+   int gcr_s0ix_size;
+   void __iomem *gcr_s0ix_base;
+
/* punit */
struct platform_device *punit_dev;
 
@@ -194,9 +201,9 @@ static inline u32 ipc_data_readl(u32 offset)
return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
 }
 
-static inline u64 gcr_data_readq(u32 offset)
+static inline u64 gcr_s0ix_data_readq(u32 offset)
 {
-   return readq(ipcdev.ipc_base + offset);
+   return readq(ipcdev.gcr_s0ix_base + offset);
 }
 
 static int intel_pmc_ipc_check_status(void)
@@ -732,7 +739,7 @@ static int ipc_plat_get_res(struct platform_device *pdev)
dev_err(>dev, "Failed to get ipc resource\n");
return -ENXIO;
}
-   size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE;
+   size = PLAT_RESOURCE_IPC_SIZE;
 
if (!request_mem_region(res->start, size, pdev->name)) {
dev_err(>dev, "Failed to request ipc resource\n");
@@ -748,8 +755,36 @@ static int ipc_plat_get_res(struct platform_device *pdev)
 
ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET;
ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
+
dev_info(>dev, "ipc res: %pR\n", res);
 
+   /* request s0ix counter reg memory */
+   ipcdev.gcr_s0ix_start = res->start + PLAT_RESOURCE_GCR_S0IX_OFFSET;
+   ipcdev.gcr_s0ix_size = PLAT_RESOURCE_GCR_S0IX_SIZE;
+
+   if (!request_mem_region(ipcdev.gcr_s0ix_start, ipcdev.gcr_s0ix_size,
+   "ipc_gcr_s0ix")) {
+   dev_err(>dev, "Failed to request s0ix mem region\n");
+   iounmap(ipcdev.ipc_base);
+   release_mem_region(res->start, size);
+   return -EBUSY;
+   }
+
+   addr = ioremap_nocache(ipcdev.gcr_s0ix_start, ipcdev.gcr_s0ix_size);
+   if (!addr) {
+   dev_err(>dev, "s0ix I/O memory remapping failed\n");
+   release_mem_region(ipcdev.gcr_s0ix_start, ipcdev.gcr_s0ix_size);
+   iounmap(ipcdev.ipc_base);
+   release_mem_region(res->start, size);
+   return -ENOMEM;
+   }
+
+   ipcdev.gcr_s0ix_base = addr;
+
+   dev_info(>dev, "s0ix mem region 0x%llx-0x%llx\n",
+ipcdev.gcr_s0ix_start,
+(ipcdev.gcr_s0ix_start + ipcdev.gcr_s0ix_size - 1));
+
ipcdev.telem_res_inval = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_TELEM_SSRAM_INDEX);
@@ -782,8 +817,8 @@ int intel_pmc_s0ix_counter_read(u64 *data)
if (!ipcdev.has_gcr_regs)
return -EACCES;
 
-   deep = gcr_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET);
-   shlw = gcr_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET);
+   deep = gcr_s0ix_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET);
+   shlw = gcr_s0ix_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET);
 
*data = S0IX_RESIDENCY_IN_USECS(deep, shlw);
 
@@ -851,12 +886,13 @@ static int ipc_plat_probe(struct platform_device *pdev)
platform_device_unregister(ipcdev.telemetry_dev);
 err_device:
iounmap(ipcdev.ipc_base);
+   iounmap(ipcdev.gcr_s0ix_base);
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_IPC_INDEX);
if (res) {
+   

[PATCH v2 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-15 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong 
---

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 11c4166..a4c74c7 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -291,6 +291,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +980,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1003,6 +1015,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1234,6 +1248,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
+
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 3/4] drm/rockchip/dsi: enable the grf clk before writing grf registers

2017-03-15 Thread Chris Zhong
For RK3399, the grf clk should be enabled before writing grf registers,
otherwise the register value can not be changed.

Signed-off-by: Chris Zhong 
---

Changes in v2:
- check the grf_clk only for RK3399

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 11c4166..a4c74c7 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -291,6 +291,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
 
+   struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +980,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
 
+   /*
+* For the RK3399, the clk of grf must be enabled before writing grf
+* register. And for RK3288 or other soc, this grf_clk must be NULL,
+* the clk_prepare_enable return true directly.
+*/
+   ret = clk_prepare_enable(dsi->grf_clk);
+   if (ret) {
+   dev_err(dsi->dev, "Failed to enable grf_clk\n");
+   return;
+   }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
 pdata->grf_dsi0_mode);
@@ -1003,6 +1015,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder 
*encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+   clk_disable_unprepare(dsi->grf_clk);
 }
 
 static int
@@ -1234,6 +1248,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
+
+   dsi->grf_clk = devm_clk_get(dev, "grf");
+   if (IS_ERR(dsi->grf_clk)) {
+   ret = PTR_ERR(dsi->grf_clk);
+   dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+   return ret;
+   }
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-15 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index a4c74c7..20ad54d 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1147,7 +1147,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
-- 
2.6.3



[PATCH v2 4/4] drm/rockchip/dsi: correct the grf_switch_reg name

2017-03-15 Thread Chris Zhong
For the RK3399, the grf_switch_reg name should be RK3399_GRF_SOC_CON20,
not RK3399_GRF_SOC_CON19.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index a4c74c7..20ad54d 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
 #define RK3288_DSI0_SEL_VOP_LITBIT(6)
 #define RK3288_DSI1_SEL_VOP_LITBIT(9)
 
-#define RK3399_GRF_SOC_CON19   0x6250
+#define RK3399_GRF_SOC_CON20   0x6250
 #define RK3399_DSI0_SEL_VOP_LITBIT(0)
 #define RK3399_DSI1_SEL_VOP_LITBIT(4)
 
@@ -1147,7 +1147,7 @@ static struct dw_mipi_dsi_plat_data 
rk3288_mipi_dsi_drv_data = {
 static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
-   .grf_switch_reg = RK3399_GRF_SOC_CON19,
+   .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
-- 
2.6.3



[PATCH v2 0/4] RK3399 dw-mipi-dsi patches

2017-03-15 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 35 +-
 2 files changed, 28 insertions(+), 9 deletions(-)

-- 
2.6.3



[PATCH v2 1/4] drm/rockchip/dsi: check phy_cfg_clk only for RK3399

2017-03-15 Thread Chris Zhong
For RK3399, the phy_cfg_clk is a required clock, if phy_cfg_clk is
disabled, MIPI phy can not work. Let's return a error if there is no
phy_cfg_clk in dts property, when the pdata match RK3399.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae..11c4166 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1227,15 +1227,13 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
clk_disable_unprepare(dsi->pclk);
}
 
-   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
-   if (IS_ERR(dsi->phy_cfg_clk)) {
-   ret = PTR_ERR(dsi->phy_cfg_clk);
-   if (ret != -ENOENT) {
+   if (pdata == _mipi_dsi_drv_data) {
+   dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+   if (IS_ERR(dsi->phy_cfg_clk)) {
+   ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
-   dsi->phy_cfg_clk = NULL;
-   dev_dbg(dev, "have not phy_cfg_clk\n");
}
 
ret = clk_prepare_enable(dsi->pllref_clk);
-- 
2.6.3



[PATCH v2 2/4] dt-bindings: add the grf clock for dw-mipi-dsi

2017-03-15 Thread Chris Zhong
For RK3399, the grf clock should be controlled by dw-mipi-dsi driver,
add the description for this clock.

Signed-off-by: Chris Zhong 
---

Changes in v2: None

 .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 188f6f7..7e17a60 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are additional required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
-- 
2.6.3



[PATCH v2 0/4] RK3399 dw-mipi-dsi patches

2017-03-15 Thread Chris Zhong
Hi all

This series set the phy_cfg_clk to be a required clock for RK3399, and
add a grf clock control in dw-mipi-dsi driver. And then correct a
register name.


Changes in v2:
- check the grf_clk only for RK3399

Chris Zhong (4):
  drm/rockchip/dsi: check phy_cfg_clk only for RK3399
  dt-bindings: add the grf clock for dw-mipi-dsi
  drm/rockchip/dsi: enable the grf clk before writing grf registers
  drm/rockchip/dsi: correct the grf_switch_reg name

 .../display/rockchip/dw_mipi_dsi_rockchip.txt  |  2 +-
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 35 +-
 2 files changed, 28 insertions(+), 9 deletions(-)

-- 
2.6.3



  1   2   3   4   5   6   7   8   9   10   >