Re: [PATCH 4.14 000/164] 4.14.6-stable review

2017-12-12 Thread Greg Kroah-Hartman
On Wed, Dec 13, 2017 at 07:48:43AM +0100, Marek Szyprowski wrote:
> Hi Shuah and Greg,
> 
> On 2017-12-12 15:47, Shuah Khan wrote:
> > On 12/12/2017 05:43 AM, Greg Kroah-Hartman wrote:
> > > This is the start of the stable review cycle for the 4.14.6 release.
> > > There are 164 patches in this series, all will be posted as a response
> > > to this one.  If anyone has any issues with these being applied, please
> > > let me know.
> > > 
> > > Responses should be made by Thu Dec 14 12:34:08 UTC 2017.
> > > Anything received after that time might be too late.
> > > 
> > > The whole patch series can be found in one patch at:
> > >   kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.6-rc1.gz
> > > or in the git tree and branch at:
> > >
> > > git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
> > > linux-4.14.y
> > > and the diffstat can be found below.
> > > 
> > > thanks,
> > > 
> > > greg k-h
> > > 
> > > Daniel Vetter 
> > >  drm: safely free connectors from connector_iter
> > > 
> > > Marek Szyprowski 
> > >  drm/bridge: analogix dp: Fix runtime PM state in get_modes() callback
> > > 
> > The above two patches have been found to be the cause of boot hang on
> > exynos Peach Pi(t) chromebooks.
> > 
> > I am adding Daniel and Marek to the thread.
> 
> The deadlock is caused by the Daniels patch. My patch only changes the order
> of device initialization what might hide or reveal bug related to Daniels
> patch.

So should I revert Daniel's patch?  Or is there already a fix for that
in Linus's tree?

thanks,

greg k-h


Re: [PATCH 4.14 000/164] 4.14.6-stable review

2017-12-12 Thread Greg Kroah-Hartman
On Wed, Dec 13, 2017 at 07:48:43AM +0100, Marek Szyprowski wrote:
> Hi Shuah and Greg,
> 
> On 2017-12-12 15:47, Shuah Khan wrote:
> > On 12/12/2017 05:43 AM, Greg Kroah-Hartman wrote:
> > > This is the start of the stable review cycle for the 4.14.6 release.
> > > There are 164 patches in this series, all will be posted as a response
> > > to this one.  If anyone has any issues with these being applied, please
> > > let me know.
> > > 
> > > Responses should be made by Thu Dec 14 12:34:08 UTC 2017.
> > > Anything received after that time might be too late.
> > > 
> > > The whole patch series can be found in one patch at:
> > >   kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.6-rc1.gz
> > > or in the git tree and branch at:
> > >
> > > git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
> > > linux-4.14.y
> > > and the diffstat can be found below.
> > > 
> > > thanks,
> > > 
> > > greg k-h
> > > 
> > > Daniel Vetter 
> > >  drm: safely free connectors from connector_iter
> > > 
> > > Marek Szyprowski 
> > >  drm/bridge: analogix dp: Fix runtime PM state in get_modes() callback
> > > 
> > The above two patches have been found to be the cause of boot hang on
> > exynos Peach Pi(t) chromebooks.
> > 
> > I am adding Daniel and Marek to the thread.
> 
> The deadlock is caused by the Daniels patch. My patch only changes the order
> of device initialization what might hide or reveal bug related to Daniels
> patch.

So should I revert Daniel's patch?  Or is there already a fix for that
in Linus's tree?

thanks,

greg k-h


Re: [rtc-linux] Re: [PATCH v4 0/2] Add support for cros-ec-rtc driver.

2017-12-12 Thread Lee Jones
On Tue, 12 Dec 2017, Alexandre Belloni wrote:

> On 12/12/2017 at 17:05:37 +0100, Alexandre Belloni wrote:
> > On 12/12/2017 at 16:41:39 +0100, Enric Balletbo Serra wrote:
> > > +   Alessandro Zummo
> > > +   Alexandre Belloni
> > > 
> > > 2017-11-10 22:55 GMT+01:00 Enric Balletbo i Serra
> > > :
> > > > Dear all,
> > > >
> > > > This is an attempt to revive some patches from that [1] patchset, some
> > > > of them are still under discussion but I think there is no reason to not
> > > > have the other two in this fourth version to land upstream meanwhile we
> > > > discuss about the others.
> > > >
> > > > [1] https://lkml.org/lkml/2017/7/12/182
> > > >
> > > > Changes since v3:
> > > > * Rebased an retested with current mainline using a Samsung Chromebook 
> > > > Plus
> > > > * Removed from patchset
> > > >   * 1/4 mfd: cros_ec: Get rid of cros_ec_check_features from 
> > > > cros_ec_dev.
> > > >   * 4/4 mfd: cros_ec: add RTC as mfd subdevice.
> > > >
> > > > Changes since v2:
> > > > - Rebase on top of mainline.
> > > > - Removed patch 'mfd: cros-ec: Fix host command buffer size' from series
> > > > as was already picked.
> > > >
> > > > Changes since v1:
> > > > - Removed patch 'iio: cros_ec_sensors: Fix return value to get raw and
> > > > calibbias data' from series as was already picked.
> > > > - Removed patch 'iio: cros_ec_sensors: Fix return value to get raw and
> > > > calibbias data' from series as was already picked.
> > > > - Patch 2/5: Acked-by: Jonathan Cameron <***@kernel.org>
> > > >
> > > > Best regards,
> > > >
> > > >  Enric
> > > >
> > > > Stephen Barber (2):
> > > >   mfd: cros_ec: Introduce RTC commands and events definitions.
> > > >   rtc: cros-ec: add cros-ec-rtc driver.
> > > >
> > > >  drivers/rtc/Kconfig  |  10 +
> > > >  drivers/rtc/Makefile |   1 +
> > > >  drivers/rtc/rtc-cros-ec.c| 413 
> > > > +++
> > > >  include/linux/mfd/cros_ec_commands.h |   8 +
> > > >  4 files changed, 432 insertions(+)
> > > >  create mode 100644 drivers/rtc/rtc-cros-ec.c
> > > >
> > > >
> > > 
> > > Sorry, I just noticed that my script to add the email recipients
> > > failed and I did not add the RTC maintainers :( So this is a gentle
> > > ping cc'ing the maintainers to take in consideration these patches. If
> > > you want I resend or something else just let me know please.
> > > 
> > 
> > I don't remember the specifics but I think the patches have the
> > necessary acks from me to go through the mfd tree (didn't we agree on
> > that ?)
> > 
> 
> This was the reply from Lee a while ago:
> 
> > On Wed, 18 Jan 2017, Alexandre Belloni wrote:
> > > I don't think that one has your ack, is it ok for me to take it?
> > 
> > This set looks MFD heavy, so it's probably best that the set goes
> > through MFD.  Once the RTC patch has been fixed of course.
> 
> The series doesn't look MFD heavy anymore so it can also go through my
> tree. I'll let Lee decide.

Fine by me.

-- 
Lee Jones
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


Re: [rtc-linux] Re: [PATCH v4 0/2] Add support for cros-ec-rtc driver.

2017-12-12 Thread Lee Jones
On Tue, 12 Dec 2017, Alexandre Belloni wrote:

> On 12/12/2017 at 17:05:37 +0100, Alexandre Belloni wrote:
> > On 12/12/2017 at 16:41:39 +0100, Enric Balletbo Serra wrote:
> > > +   Alessandro Zummo
> > > +   Alexandre Belloni
> > > 
> > > 2017-11-10 22:55 GMT+01:00 Enric Balletbo i Serra
> > > :
> > > > Dear all,
> > > >
> > > > This is an attempt to revive some patches from that [1] patchset, some
> > > > of them are still under discussion but I think there is no reason to not
> > > > have the other two in this fourth version to land upstream meanwhile we
> > > > discuss about the others.
> > > >
> > > > [1] https://lkml.org/lkml/2017/7/12/182
> > > >
> > > > Changes since v3:
> > > > * Rebased an retested with current mainline using a Samsung Chromebook 
> > > > Plus
> > > > * Removed from patchset
> > > >   * 1/4 mfd: cros_ec: Get rid of cros_ec_check_features from 
> > > > cros_ec_dev.
> > > >   * 4/4 mfd: cros_ec: add RTC as mfd subdevice.
> > > >
> > > > Changes since v2:
> > > > - Rebase on top of mainline.
> > > > - Removed patch 'mfd: cros-ec: Fix host command buffer size' from series
> > > > as was already picked.
> > > >
> > > > Changes since v1:
> > > > - Removed patch 'iio: cros_ec_sensors: Fix return value to get raw and
> > > > calibbias data' from series as was already picked.
> > > > - Removed patch 'iio: cros_ec_sensors: Fix return value to get raw and
> > > > calibbias data' from series as was already picked.
> > > > - Patch 2/5: Acked-by: Jonathan Cameron <***@kernel.org>
> > > >
> > > > Best regards,
> > > >
> > > >  Enric
> > > >
> > > > Stephen Barber (2):
> > > >   mfd: cros_ec: Introduce RTC commands and events definitions.
> > > >   rtc: cros-ec: add cros-ec-rtc driver.
> > > >
> > > >  drivers/rtc/Kconfig  |  10 +
> > > >  drivers/rtc/Makefile |   1 +
> > > >  drivers/rtc/rtc-cros-ec.c| 413 
> > > > +++
> > > >  include/linux/mfd/cros_ec_commands.h |   8 +
> > > >  4 files changed, 432 insertions(+)
> > > >  create mode 100644 drivers/rtc/rtc-cros-ec.c
> > > >
> > > >
> > > 
> > > Sorry, I just noticed that my script to add the email recipients
> > > failed and I did not add the RTC maintainers :( So this is a gentle
> > > ping cc'ing the maintainers to take in consideration these patches. If
> > > you want I resend or something else just let me know please.
> > > 
> > 
> > I don't remember the specifics but I think the patches have the
> > necessary acks from me to go through the mfd tree (didn't we agree on
> > that ?)
> > 
> 
> This was the reply from Lee a while ago:
> 
> > On Wed, 18 Jan 2017, Alexandre Belloni wrote:
> > > I don't think that one has your ack, is it ok for me to take it?
> > 
> > This set looks MFD heavy, so it's probably best that the set goes
> > through MFD.  Once the RTC patch has been fixed of course.
> 
> The series doesn't look MFD heavy anymore so it can also go through my
> tree. I'll let Lee decide.

Fine by me.

-- 
Lee Jones
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


Re: [PATCH] cgroup/cpuset: fix circular locking dependency

2017-12-12 Thread Prateek Sood
On 12/11/2017 08:50 PM, Tejun Heo wrote:
> Hello, Peter.
> 
> On Tue, Dec 05, 2017 at 12:01:17AM +0100, Peter Zijlstra wrote:
>>> AFAICS, this should remove the circular dependency you originally
>>> reported.  I'll revert the two cpuset commits for now.
>>
>> So I liked his patches in that we would be able to go back to
>> synchronous sched_domain building.
> 
> Ah, yeah, that's a separate issue but didn't we intentionally make
> that asynchronous?  IIRC, cpuset migration can take a really long time
> when the memory migration is turned on and doing that synchronously
> could mess up the system.
> 
> Thanks.
> 

Hi TJ,

This change makes the usage of cpuset_hotplug_workfn() from cpu
hotplug path synchronous. For memory hotplug it still remains
asynchronous.

Memory migration happening from cpuset_hotplug_workfn() is
already asynchronous by queuing cpuset_migrate_mm_workfn() in
cpuset_migrate_mm_wq.

cpuset_hotplug_workfn()
   cpuset_hotplug_workfn(()
  cpuset_migrate_mm()
 queue_work(cpuset_migrate_mm_wq)

It seems that memory migration latency might not have
impact with this change.

Please let me know if you meant something else by cpuset
migration taking time when memory migration is turned on.


Thanks

-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project


Re: [PATCH] cgroup/cpuset: fix circular locking dependency

2017-12-12 Thread Prateek Sood
On 12/11/2017 08:50 PM, Tejun Heo wrote:
> Hello, Peter.
> 
> On Tue, Dec 05, 2017 at 12:01:17AM +0100, Peter Zijlstra wrote:
>>> AFAICS, this should remove the circular dependency you originally
>>> reported.  I'll revert the two cpuset commits for now.
>>
>> So I liked his patches in that we would be able to go back to
>> synchronous sched_domain building.
> 
> Ah, yeah, that's a separate issue but didn't we intentionally make
> that asynchronous?  IIRC, cpuset migration can take a really long time
> when the memory migration is turned on and doing that synchronously
> could mess up the system.
> 
> Thanks.
> 

Hi TJ,

This change makes the usage of cpuset_hotplug_workfn() from cpu
hotplug path synchronous. For memory hotplug it still remains
asynchronous.

Memory migration happening from cpuset_hotplug_workfn() is
already asynchronous by queuing cpuset_migrate_mm_workfn() in
cpuset_migrate_mm_wq.

cpuset_hotplug_workfn()
   cpuset_hotplug_workfn(()
  cpuset_migrate_mm()
 queue_work(cpuset_migrate_mm_wq)

It seems that memory migration latency might not have
impact with this change.

Please let me know if you meant something else by cpuset
migration taking time when memory migration is turned on.


Thanks

-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project


[PATCH 1/1] arm: sunxi: Add alternative pins for spi0

2017-12-12 Thread Stefan Mavrodiev
Allwinner A10/A13/A20 SoCs have pinmux for spi0
on port C. The patch adds these pins in the respective
dts includes.

Signed-off-by: Stefan Mavrodiev 
---
 arch/arm/boot/dts/sun4i-a10.dtsi | 10 ++
 arch/arm/boot/dts/sun5i.dtsi | 10 ++
 arch/arm/boot/dts/sun7i-a20.dtsi | 10 ++
 3 files changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 5840f5c..d835741 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -705,11 +705,21 @@
bias-pull-up;
};
 
+   spi0_pc_pins: spi0-pc-pins {
+   pins = "PC0", "PC1", "PC2";
+   function = "spi0";
+   };
+
spi0_pi_pins: spi0-pi-pins {
pins = "PI11", "PI12", "PI13";
function = "spi0";
};
 
+   spi0_cs0_pc_pin: spi0-cs0-pc-pin {
+   pins = "PC23";
+   function = "spi0";
+   };
+
spi0_cs0_pi_pin: spi0-cs0-pi-pin {
pins = "PI10";
function = "spi0";
diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
index 07f2248..9290e26 100644
--- a/arch/arm/boot/dts/sun5i.dtsi
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -492,6 +492,16 @@
function = "nand0";
};
 
+   spi0_pins_a: spi0@0 {
+   pins = "PC0", "PC1", "PC2";
+   function = "spi0";
+   };
+
+   spi0_cs0_pins_a: spi0-cs0@0 {
+   pins = "PC3";
+   function = "spi0";
+   };
+
spi2_pins_a: spi2@0 {
pins = "PE1", "PE2", "PE3";
function = "spi2";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 59655e4..6930527 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -838,11 +838,21 @@
function = "spi0";
};
 
+   spi0_pins_b: spi0@1 {
+   pins = "PC0", "PC1", "PC2";
+   function = "spi0";
+   };
+
spi0_cs0_pins_a: spi0_cs0@0 {
pins = "PI10";
function = "spi0";
};
 
+   spi0_cs0_pins_b: spi0_cs0@1 {
+   pins = "PC23";
+   function = "spi0";
+   };
+
spi0_cs1_pins_a: spi0_cs1@0 {
pins = "PI14";
function = "spi0";
-- 
2.7.4



[PATCH 1/1] arm: sunxi: Add alternative pins for spi0

2017-12-12 Thread Stefan Mavrodiev
Allwinner A10/A13/A20 SoCs have pinmux for spi0
on port C. The patch adds these pins in the respective
dts includes.

Signed-off-by: Stefan Mavrodiev 
---
 arch/arm/boot/dts/sun4i-a10.dtsi | 10 ++
 arch/arm/boot/dts/sun5i.dtsi | 10 ++
 arch/arm/boot/dts/sun7i-a20.dtsi | 10 ++
 3 files changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 5840f5c..d835741 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -705,11 +705,21 @@
bias-pull-up;
};
 
+   spi0_pc_pins: spi0-pc-pins {
+   pins = "PC0", "PC1", "PC2";
+   function = "spi0";
+   };
+
spi0_pi_pins: spi0-pi-pins {
pins = "PI11", "PI12", "PI13";
function = "spi0";
};
 
+   spi0_cs0_pc_pin: spi0-cs0-pc-pin {
+   pins = "PC23";
+   function = "spi0";
+   };
+
spi0_cs0_pi_pin: spi0-cs0-pi-pin {
pins = "PI10";
function = "spi0";
diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
index 07f2248..9290e26 100644
--- a/arch/arm/boot/dts/sun5i.dtsi
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -492,6 +492,16 @@
function = "nand0";
};
 
+   spi0_pins_a: spi0@0 {
+   pins = "PC0", "PC1", "PC2";
+   function = "spi0";
+   };
+
+   spi0_cs0_pins_a: spi0-cs0@0 {
+   pins = "PC3";
+   function = "spi0";
+   };
+
spi2_pins_a: spi2@0 {
pins = "PE1", "PE2", "PE3";
function = "spi2";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 59655e4..6930527 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -838,11 +838,21 @@
function = "spi0";
};
 
+   spi0_pins_b: spi0@1 {
+   pins = "PC0", "PC1", "PC2";
+   function = "spi0";
+   };
+
spi0_cs0_pins_a: spi0_cs0@0 {
pins = "PI10";
function = "spi0";
};
 
+   spi0_cs0_pins_b: spi0_cs0@1 {
+   pins = "PC23";
+   function = "spi0";
+   };
+
spi0_cs1_pins_a: spi0_cs1@0 {
pins = "PI14";
function = "spi0";
-- 
2.7.4



Re: [BUG] skge: a possible sleep-in-atomic bug in skge_remove

2017-12-12 Thread Jia-Ju Bai


On 2017/12/13 13:18, Stephen Hemminger wrote:

On Tue, 12 Dec 2017 20:57:01 -0500 (EST)
David Miller  wrote:


From: Stephen Hemminger 
Date: Tue, 12 Dec 2017 10:22:40 -0800


On Tue, 12 Dec 2017 08:34:45 -0500 (EST)
David Miller  wrote:
   

From: Jia-Ju Bai 
Date: Tue, 12 Dec 2017 16:38:12 +0800
   

According to drivers/net/ethernet/marvell/skge.c, the driver may sleep
under a spinlock.
The function call path is:
skge_remove (acquire the spinlock)
   free_irq --> may sleep

I do not find a good way to fix it, so I only report.
This possible bug is found by my static analysis tool (DSAC) and
checked by my code review.

This was added by:

commit a9e9fd7182332d0cf5f3e601df3e71dd431b70d7
Author: Stephen Hemminger 
Date:   Tue Sep 27 13:41:37 2011 -0400

 skge: handle irq better on single port card

I think the free_irq() can be moved below the unlock.

Stephen, please take a look.

The IRQ was being free twice.
How did you see it, I really doubt any multi-port SKGE cards
still exist.

He sees it by reading the code, please take a look at this
and move the free_irq() out of the spin locked section since
it can sleep.

Thanks, I was hoping for some automated static analysis tool.


This bug was found by an automated static analysis tool named DSAC, 
which is written by myself.

Then I manually checked driver source code, and finally sent the bug report.


Thanks,
Jia-Ju Bai


Re: [BUG] skge: a possible sleep-in-atomic bug in skge_remove

2017-12-12 Thread Jia-Ju Bai


On 2017/12/13 13:18, Stephen Hemminger wrote:

On Tue, 12 Dec 2017 20:57:01 -0500 (EST)
David Miller  wrote:


From: Stephen Hemminger 
Date: Tue, 12 Dec 2017 10:22:40 -0800


On Tue, 12 Dec 2017 08:34:45 -0500 (EST)
David Miller  wrote:
   

From: Jia-Ju Bai 
Date: Tue, 12 Dec 2017 16:38:12 +0800
   

According to drivers/net/ethernet/marvell/skge.c, the driver may sleep
under a spinlock.
The function call path is:
skge_remove (acquire the spinlock)
   free_irq --> may sleep

I do not find a good way to fix it, so I only report.
This possible bug is found by my static analysis tool (DSAC) and
checked by my code review.

This was added by:

commit a9e9fd7182332d0cf5f3e601df3e71dd431b70d7
Author: Stephen Hemminger 
Date:   Tue Sep 27 13:41:37 2011 -0400

 skge: handle irq better on single port card

I think the free_irq() can be moved below the unlock.

Stephen, please take a look.

The IRQ was being free twice.
How did you see it, I really doubt any multi-port SKGE cards
still exist.

He sees it by reading the code, please take a look at this
and move the free_irq() out of the spin locked section since
it can sleep.

Thanks, I was hoping for some automated static analysis tool.


This bug was found by an automated static analysis tool named DSAC, 
which is written by myself.

Then I manually checked driver source code, and finally sent the bug report.


Thanks,
Jia-Ju Bai


Re: [PATCH v2 04/13] dt-bindings: pinctrl: Add bindings for Microsemi Ocelot

2017-12-12 Thread Linus Walleij
On Fri, Dec 8, 2017 at 4:46 PM, Alexandre Belloni
 wrote:

> Add the documentation for the Microsemi Ocelot pinmuxing and gpio
> controller.
>
> Cc: Linus Walleij 
> Cc: linux-g...@vger.kernel.org
> Signed-off-by: Alexandre Belloni 
> Acked-by: Rob Herring 

Patch applied.

Yours,
Linus Walleij


Re: [PATCH v2 04/13] dt-bindings: pinctrl: Add bindings for Microsemi Ocelot

2017-12-12 Thread Linus Walleij
On Fri, Dec 8, 2017 at 4:46 PM, Alexandre Belloni
 wrote:

> Add the documentation for the Microsemi Ocelot pinmuxing and gpio
> controller.
>
> Cc: Linus Walleij 
> Cc: linux-g...@vger.kernel.org
> Signed-off-by: Alexandre Belloni 
> Acked-by: Rob Herring 

Patch applied.

Yours,
Linus Walleij


Re: [BUG] scsi/qla2xxx: a possible sleep-in-atomic bug in qlt_get_tag

2017-12-12 Thread Jia-Ju Bai


On 2017/12/13 12:42, James Bottomley wrote:

On Wed, 2017-12-13 at 11:18 +0800, Jia-Ju Bai wrote:

The driver may sleep under a spinlock.
The function call paths are:
qlt_handle_abts_recv_work (acquire the spinlock)
qlt_response_pkt_all_vps
  qlt_response_pkt
qlt_handle_cmd_for_atio
  qlt_get_tag
percpu_ida_alloc --> may sleep

qla82xx_msix_rsp_q (acquire the spinlock)
qla24xx_process_response_queue
  qlt_handle_abts_recv
qlt_response_pkt_all_vps
  qlt_response_pkt
qlt_handle_cmd_for_atio
  qlt_get_tag
percpu_ida_alloc --> may sleep-in-atomic

qla24xx_intr_handler (acquire the spinlock)
qla24xx_process_response_queue
  qlt_handle_abts_recv
qlt_response_pkt
  qlt_handle_cmd_for_atio
qlt_get_tag
  percpu_ida_alloc --> may sleep

I do not find a good way to fix it, so I only report.
This possible bug is found by my static analysis tool (DSAC) and
checked by my code review.

The report is incorrect: percpu_ida_alloc with state==TASK_RUNNING is
atomic (and interrupt) safe which appears to be the case here.

James



Thanks for your reply :)
I have checked the definition of percpu_ida_alloc, and I think you are 
right.

Sorry for my incorrect bug report.


Thanks,
Jia-Ju Bai


Re: [BUG] scsi/qla2xxx: a possible sleep-in-atomic bug in qlt_get_tag

2017-12-12 Thread Jia-Ju Bai


On 2017/12/13 12:42, James Bottomley wrote:

On Wed, 2017-12-13 at 11:18 +0800, Jia-Ju Bai wrote:

The driver may sleep under a spinlock.
The function call paths are:
qlt_handle_abts_recv_work (acquire the spinlock)
qlt_response_pkt_all_vps
  qlt_response_pkt
qlt_handle_cmd_for_atio
  qlt_get_tag
percpu_ida_alloc --> may sleep

qla82xx_msix_rsp_q (acquire the spinlock)
qla24xx_process_response_queue
  qlt_handle_abts_recv
qlt_response_pkt_all_vps
  qlt_response_pkt
qlt_handle_cmd_for_atio
  qlt_get_tag
percpu_ida_alloc --> may sleep-in-atomic

qla24xx_intr_handler (acquire the spinlock)
qla24xx_process_response_queue
  qlt_handle_abts_recv
qlt_response_pkt
  qlt_handle_cmd_for_atio
qlt_get_tag
  percpu_ida_alloc --> may sleep

I do not find a good way to fix it, so I only report.
This possible bug is found by my static analysis tool (DSAC) and
checked by my code review.

The report is incorrect: percpu_ida_alloc with state==TASK_RUNNING is
atomic (and interrupt) safe which appears to be the case here.

James



Thanks for your reply :)
I have checked the definition of percpu_ida_alloc, and I think you are 
right.

Sorry for my incorrect bug report.


Thanks,
Jia-Ju Bai


Re: general protection fault in page_mapping

2017-12-12 Thread Vlastimil Babka
On 12/12/2017 06:03 PM, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on  
> 82bcf1def3b5f1251177ad47c44f7e17af039b4b
> git://git.cmpxchg.org/linux-mmots.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> C reproducer is attached
> syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> for information about syzkaller reproducers
> 
> 
> audit: type=1400 audit(1512751226.892:7): avc:  denied  { map } for   
> pid=3149 comm="syzkaller233597" path="/root/syzkaller233597068" dev="sda1"  
> ino=16481 scontext=unconfined_u:system_r:insmod_t:s0-s0:c0.c1023  
> tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=1
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> Dumping ftrace buffer:
> (ftrace buffer empty)
> Modules linked in:
> CPU: 0 PID: 3149 Comm: syzkaller233597 Not tainted 4.15.0-rc2-mm1+ #39
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS  
> Google 01/01/2011
> RIP: 0010:__read_once_size include/linux/compiler.h:183 [inline]
> RIP: 0010:compound_head include/linux/page-flags.h:147 [inline]
> RIP: 0010:page_mapping+0xa4/0x530 mm/util.c:475
> RSP: 0018:8801c5177320 EFLAGS: 00010202
> RAX: 0004 RBX: 110038a2ee65 RCX: 81950c5d
> RDX:  RSI: 110038a2ef03 RDI: 
> RBP: 8801c5177470 R08: ed0038a6fbac R09: 8801c537dd40
> R10: 8801d6e8c518 R11: ed0038a6fbab R12: 
> R13: 8801c5177448 R14: dc00 R15: 0020
> FS:  021da880() GS:8801db20() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 20a23000 CR3: 0001c6bf5000 CR4: 001406f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> Call Trace:
>   set_page_dirty+0xb9/0x5d0 mm/page-writeback.c:2544
>   rds_atomic_free_op+0xc2/0x330 net/rds/rdma.c:481

The NULL page pointer was obtained in the function above, so CCing rdma.

>   rds_message_purge net/rds/message.c:79 [inline]
>   rds_message_put+0x53c/0x6b0 net/rds/message.c:91
>   rds_sendmsg+0x14ee/0x1f90 net/rds/send.c:1204
>   sock_sendmsg_nosec net/socket.c:636 [inline]
>   sock_sendmsg+0xca/0x110 net/socket.c:646
>   ___sys_sendmsg+0x75b/0x8a0 net/socket.c:2026
>   __sys_sendmsg+0xe5/0x210 net/socket.c:2060
>   SYSC_sendmsg net/socket.c:2071 [inline]
>   SyS_sendmsg+0x2d/0x50 net/socket.c:2067
>   entry_SYSCALL_64_fastpath+0x1f/0x96
> RIP: 0033:0x43fe49
> RSP: 002b:7fffab075338 EFLAGS: 0217 ORIG_RAX: 002e
> RAX: ffda RBX: 004002c8 RCX: 0043fe49
> RDX:  RSI: 20159fc8 RDI: 0003
> RBP: 006ca018 R08:  R09: 
> R10:  R11: 0217 R12: 004017b0
> R13: 00401840 R14:  R15: 
> Code: f2 f2 f2 c7 40 14 00 f2 f2 f2 c7 40 18 f2 f2 f2 f2 c7 40 1c 00 f2 f2  
> f2 c7 40 20 f3 f3 f3 f3 e8 43 29 db ff 4c 89 f8 48 c1 e8 03 <42> 80 3c 30  
> 00 0f 85 41 04 00 00 4d 8d b5 00 ff ff ff 48 ba 00
> RIP: __read_once_size include/linux/compiler.h:183 [inline] RSP:  
> 8801c5177320
> RIP: compound_head include/linux/page-flags.h:147 [inline] RSP:  
> 8801c5177320
> RIP: page_mapping+0xa4/0x530 mm/util.c:475 RSP: 8801c5177320
> ---[ end trace f878597b0d0664a0 ]---
> Kernel panic - not syncing: Fatal exception
> Dumping ftrace buffer:
> (ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..
> 
> 
> ---
> This bug is generated by a dumb bot. It may contain errors.
> See https://goo.gl/tpsmEJ for details.
> Direct all questions to syzkal...@googlegroups.com.
> Please credit me with: Reported-by: syzbot 
> 
> syzbot will keep track of this bug report.
> Once a fix for this bug is merged into any tree, reply to this email with:
> #syz fix: exact-commit-title
> If you want to test a patch for this bug, please reply with:
> #syz test: git://repo/address.git branch
> and provide the patch inline or as an attachment.
> To mark this as a duplicate of another syzbot report, please reply with:
> #syz dup: exact-subject-of-another-report
> If it's a one-off invalid bug report, please reply with:
> #syz invalid
> Note: if the crash happens again, it will cause creation of a new bug  
> report.
> Note: all commands must start from beginning of the line in the email body.
> 
> 
> config.txt
> 
> 
> #
> # Automatically generated file; DO NOT EDIT.
> # Linux/x86 4.15.0-rc2 Kernel Configuration
> #
> CONFIG_64BIT=y
> CONFIG_X86_64=y
> CONFIG_X86=y
> CONFIG_INSTRUCTION_DECODER=y
> CONFIG_OUTPUT_FORMAT="elf64-x86-64"
> CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
> 

Re: general protection fault in page_mapping

2017-12-12 Thread Vlastimil Babka
On 12/12/2017 06:03 PM, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on  
> 82bcf1def3b5f1251177ad47c44f7e17af039b4b
> git://git.cmpxchg.org/linux-mmots.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> C reproducer is attached
> syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> for information about syzkaller reproducers
> 
> 
> audit: type=1400 audit(1512751226.892:7): avc:  denied  { map } for   
> pid=3149 comm="syzkaller233597" path="/root/syzkaller233597068" dev="sda1"  
> ino=16481 scontext=unconfined_u:system_r:insmod_t:s0-s0:c0.c1023  
> tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=1
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> Dumping ftrace buffer:
> (ftrace buffer empty)
> Modules linked in:
> CPU: 0 PID: 3149 Comm: syzkaller233597 Not tainted 4.15.0-rc2-mm1+ #39
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS  
> Google 01/01/2011
> RIP: 0010:__read_once_size include/linux/compiler.h:183 [inline]
> RIP: 0010:compound_head include/linux/page-flags.h:147 [inline]
> RIP: 0010:page_mapping+0xa4/0x530 mm/util.c:475
> RSP: 0018:8801c5177320 EFLAGS: 00010202
> RAX: 0004 RBX: 110038a2ee65 RCX: 81950c5d
> RDX:  RSI: 110038a2ef03 RDI: 
> RBP: 8801c5177470 R08: ed0038a6fbac R09: 8801c537dd40
> R10: 8801d6e8c518 R11: ed0038a6fbab R12: 
> R13: 8801c5177448 R14: dc00 R15: 0020
> FS:  021da880() GS:8801db20() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 20a23000 CR3: 0001c6bf5000 CR4: 001406f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> Call Trace:
>   set_page_dirty+0xb9/0x5d0 mm/page-writeback.c:2544
>   rds_atomic_free_op+0xc2/0x330 net/rds/rdma.c:481

The NULL page pointer was obtained in the function above, so CCing rdma.

>   rds_message_purge net/rds/message.c:79 [inline]
>   rds_message_put+0x53c/0x6b0 net/rds/message.c:91
>   rds_sendmsg+0x14ee/0x1f90 net/rds/send.c:1204
>   sock_sendmsg_nosec net/socket.c:636 [inline]
>   sock_sendmsg+0xca/0x110 net/socket.c:646
>   ___sys_sendmsg+0x75b/0x8a0 net/socket.c:2026
>   __sys_sendmsg+0xe5/0x210 net/socket.c:2060
>   SYSC_sendmsg net/socket.c:2071 [inline]
>   SyS_sendmsg+0x2d/0x50 net/socket.c:2067
>   entry_SYSCALL_64_fastpath+0x1f/0x96
> RIP: 0033:0x43fe49
> RSP: 002b:7fffab075338 EFLAGS: 0217 ORIG_RAX: 002e
> RAX: ffda RBX: 004002c8 RCX: 0043fe49
> RDX:  RSI: 20159fc8 RDI: 0003
> RBP: 006ca018 R08:  R09: 
> R10:  R11: 0217 R12: 004017b0
> R13: 00401840 R14:  R15: 
> Code: f2 f2 f2 c7 40 14 00 f2 f2 f2 c7 40 18 f2 f2 f2 f2 c7 40 1c 00 f2 f2  
> f2 c7 40 20 f3 f3 f3 f3 e8 43 29 db ff 4c 89 f8 48 c1 e8 03 <42> 80 3c 30  
> 00 0f 85 41 04 00 00 4d 8d b5 00 ff ff ff 48 ba 00
> RIP: __read_once_size include/linux/compiler.h:183 [inline] RSP:  
> 8801c5177320
> RIP: compound_head include/linux/page-flags.h:147 [inline] RSP:  
> 8801c5177320
> RIP: page_mapping+0xa4/0x530 mm/util.c:475 RSP: 8801c5177320
> ---[ end trace f878597b0d0664a0 ]---
> Kernel panic - not syncing: Fatal exception
> Dumping ftrace buffer:
> (ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..
> 
> 
> ---
> This bug is generated by a dumb bot. It may contain errors.
> See https://goo.gl/tpsmEJ for details.
> Direct all questions to syzkal...@googlegroups.com.
> Please credit me with: Reported-by: syzbot 
> 
> syzbot will keep track of this bug report.
> Once a fix for this bug is merged into any tree, reply to this email with:
> #syz fix: exact-commit-title
> If you want to test a patch for this bug, please reply with:
> #syz test: git://repo/address.git branch
> and provide the patch inline or as an attachment.
> To mark this as a duplicate of another syzbot report, please reply with:
> #syz dup: exact-subject-of-another-report
> If it's a one-off invalid bug report, please reply with:
> #syz invalid
> Note: if the crash happens again, it will cause creation of a new bug  
> report.
> Note: all commands must start from beginning of the line in the email body.
> 
> 
> config.txt
> 
> 
> #
> # Automatically generated file; DO NOT EDIT.
> # Linux/x86 4.15.0-rc2 Kernel Configuration
> #
> CONFIG_64BIT=y
> CONFIG_X86_64=y
> CONFIG_X86=y
> CONFIG_INSTRUCTION_DECODER=y
> CONFIG_OUTPUT_FORMAT="elf64-x86-64"
> CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
> CONFIG_LOCKDEP_SUPPORT=y
> 

Re: [PATCH v5 8/9] pinctrl: axp209: add support for AXP813 GPIOs

2017-12-12 Thread Linus Walleij
On Fri, Dec 8, 2017 at 2:41 PM, Quentin Schulz
 wrote:

>> - pctl->desc = _data;
>> + pctl->desc = (struct axp20x_pctrl_desc *)of_device_get_match_data(dev);
>>   pctl->regmap = axp20x->regmap;
>>   pctl->dev = >dev;
>>
>
> I am using pctl->desc before retrieving it, thus dereferencing from a
> null pointer.
>
> We just have to move
> pctl->chip.ngpio= pctl->desc->npins;
> after
> pctl->desc = (struct axp20x_pctrl_desc *)of_device_get_match_data(dev);
>
> Linus, I guess that I should send a patch to fix this or is there an
> other way not to have to apply such a small and dumb patch?

Just send a patch based on my pin control tree "devel" branch or
linux-next, it's cool.

Things like this happens all the time.

Yours,
Linus Walleij


Re: [PATCH v5 8/9] pinctrl: axp209: add support for AXP813 GPIOs

2017-12-12 Thread Linus Walleij
On Fri, Dec 8, 2017 at 2:41 PM, Quentin Schulz
 wrote:

>> - pctl->desc = _data;
>> + pctl->desc = (struct axp20x_pctrl_desc *)of_device_get_match_data(dev);
>>   pctl->regmap = axp20x->regmap;
>>   pctl->dev = >dev;
>>
>
> I am using pctl->desc before retrieving it, thus dereferencing from a
> null pointer.
>
> We just have to move
> pctl->chip.ngpio= pctl->desc->npins;
> after
> pctl->desc = (struct axp20x_pctrl_desc *)of_device_get_match_data(dev);
>
> Linus, I guess that I should send a patch to fix this or is there an
> other way not to have to apply such a small and dumb patch?

Just send a patch based on my pin control tree "devel" branch or
linux-next, it's cool.

Things like this happens all the time.

Yours,
Linus Walleij


Re: [PATCH v5 0/4] ARM: ep93xx: ts72xx: Add support for BK3 board

2017-12-12 Thread Linus Walleij
On Tue, Dec 12, 2017 at 12:36 AM, Lukasz Majewski  wrote:

> This patch series adds support for Liebherr's BK3 board, being
> a derivative of TS72XX design.

All looks good.
Acked-by: Linus Walleij 

Out of curiosity: Liebherr is obviously doing heavy-duty industrial
control systems. Likewise Hartley is doing similar business over
at Vision Engravings.

Is the situation such that there is a whole bunch of industrial
systems out there, in active use and needing future upgrades,
that use the EP93xx?

Arnd has been nudging me to do DT conversion for EP93xx
so if there are many active industrial users of these
I should prioritize it, because these things have 20+ years
support cycles.

We also need to think about upholding support in GCC for
ARMv4(t) for the foreseeable future if there is a big web of
random deeply embedded systems out there that will need
updates.

Yours,
Linus Walleij


Re: [PATCH v5 0/4] ARM: ep93xx: ts72xx: Add support for BK3 board

2017-12-12 Thread Linus Walleij
On Tue, Dec 12, 2017 at 12:36 AM, Lukasz Majewski  wrote:

> This patch series adds support for Liebherr's BK3 board, being
> a derivative of TS72XX design.

All looks good.
Acked-by: Linus Walleij 

Out of curiosity: Liebherr is obviously doing heavy-duty industrial
control systems. Likewise Hartley is doing similar business over
at Vision Engravings.

Is the situation such that there is a whole bunch of industrial
systems out there, in active use and needing future upgrades,
that use the EP93xx?

Arnd has been nudging me to do DT conversion for EP93xx
so if there are many active industrial users of these
I should prioritize it, because these things have 20+ years
support cycles.

We also need to think about upholding support in GCC for
ARMv4(t) for the foreseeable future if there is a big web of
random deeply embedded systems out there that will need
updates.

Yours,
Linus Walleij


Re: [PATCH] spi: s3c64xx: add SPDX identifier

2017-12-12 Thread Krzysztof Kozlowski
On Wed, Dec 13, 2017 at 2:48 AM, Andi Shyti  wrote:
> Hi Krzysztof,
>
>> > Here, this should be as a top line:
>> >
>> > // SPDX-License-Identifier: GPL-2.0+
>> >
>> >
>> > So I agree with the SPDX id but also pointing to the use of the C++ //
>> > comment style as requested by Linus [1]
>>
>> Thanks for the reference. I see that Linus prefers converting entire
>> comment into // style. I was not arguing about SPDX line but entire
>> existing copyright comment which follows it:
>>
>> > +//
>> > +// Copyright (c) 2009 Samsung Electronics Co., Ltd.
>> > +//  Jaswinder Singh 
>
> it just looks ugly to me to have something like
>
>   // SPDX...
>
>   /*
>* Copyright (c)...
>*  Jasw...
>*/
>
> I would make everything of the '//' style (I've also seen that
> this is the trend also in other subsystems), but honestly I don't
> really care. If you're strong on not moving entirely in '//' style
> then I can resend it with the double comment style.

Let's follow Linus' preference - entire commend converted as you did already.

Thanks,
Krzysztof


Re: [PATCH] spi: s3c64xx: add SPDX identifier

2017-12-12 Thread Krzysztof Kozlowski
On Wed, Dec 13, 2017 at 2:48 AM, Andi Shyti  wrote:
> Hi Krzysztof,
>
>> > Here, this should be as a top line:
>> >
>> > // SPDX-License-Identifier: GPL-2.0+
>> >
>> >
>> > So I agree with the SPDX id but also pointing to the use of the C++ //
>> > comment style as requested by Linus [1]
>>
>> Thanks for the reference. I see that Linus prefers converting entire
>> comment into // style. I was not arguing about SPDX line but entire
>> existing copyright comment which follows it:
>>
>> > +//
>> > +// Copyright (c) 2009 Samsung Electronics Co., Ltd.
>> > +//  Jaswinder Singh 
>
> it just looks ugly to me to have something like
>
>   // SPDX...
>
>   /*
>* Copyright (c)...
>*  Jasw...
>*/
>
> I would make everything of the '//' style (I've also seen that
> this is the trend also in other subsystems), but honestly I don't
> really care. If you're strong on not moving entirely in '//' style
> then I can resend it with the double comment style.

Let's follow Linus' preference - entire commend converted as you did already.

Thanks,
Krzysztof


[PATCH V8 3/7] device property: Introduce a common API to fetch device match data

2017-12-12 Thread Sinan Kaya
There is an OF/ACPI function to obtain the driver data. We want to hide
OF/ACPI details from the device drivers and abstract following the device
family of functions.

Signed-off-by: Sinan Kaya 
Reviewed-by: Rob Herring 
Acked-by: Sakari Ailus 
---
 drivers/base/property.c  | 7 +++
 include/linux/fwnode.h   | 4 
 include/linux/property.h | 2 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..09eaac9 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1340,3 +1340,10 @@ int fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
 }
 EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
+
+void *device_get_match_data(struct device *dev)
+{
+   return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data,
+ dev);
+}
+EXPORT_SYMBOL_GPL(device_get_match_data);
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 411a84c..4fa1a48 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -15,6 +15,7 @@
 #include 
 
 struct fwnode_operations;
+struct device;
 
 struct fwnode_handle {
struct fwnode_handle *secondary;
@@ -51,6 +52,7 @@ struct fwnode_reference_args {
  * struct fwnode_operations - Operations for fwnode interface
  * @get: Get a reference to an fwnode.
  * @put: Put a reference to an fwnode.
+ * @device_get_match_data: Return the device driver match data.
  * @property_present: Return true if a property is present.
  * @property_read_integer_array: Read an array of integer properties. Return
  *  zero on success, a negative error code
@@ -71,6 +73,8 @@ struct fwnode_operations {
struct fwnode_handle *(*get)(struct fwnode_handle *fwnode);
void (*put)(struct fwnode_handle *fwnode);
bool (*device_is_available)(const struct fwnode_handle *fwnode);
+   void *(*device_get_match_data)(const struct fwnode_handle *fwnode,
+  const struct device *dev);
bool (*property_present)(const struct fwnode_handle *fwnode,
 const char *propname);
int (*property_read_int_array)(const struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..6653ed4 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -275,6 +275,8 @@ int device_add_properties(struct device *dev,
 
 enum dev_dma_attr device_get_dma_attr(struct device *dev);
 
+void *device_get_match_data(struct device *dev);
+
 int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
-- 
1.9.1



[PATCH V8 3/7] device property: Introduce a common API to fetch device match data

2017-12-12 Thread Sinan Kaya
There is an OF/ACPI function to obtain the driver data. We want to hide
OF/ACPI details from the device drivers and abstract following the device
family of functions.

Signed-off-by: Sinan Kaya 
Reviewed-by: Rob Herring 
Acked-by: Sakari Ailus 
---
 drivers/base/property.c  | 7 +++
 include/linux/fwnode.h   | 4 
 include/linux/property.h | 2 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..09eaac9 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1340,3 +1340,10 @@ int fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
 }
 EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
+
+void *device_get_match_data(struct device *dev)
+{
+   return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data,
+ dev);
+}
+EXPORT_SYMBOL_GPL(device_get_match_data);
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 411a84c..4fa1a48 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -15,6 +15,7 @@
 #include 
 
 struct fwnode_operations;
+struct device;
 
 struct fwnode_handle {
struct fwnode_handle *secondary;
@@ -51,6 +52,7 @@ struct fwnode_reference_args {
  * struct fwnode_operations - Operations for fwnode interface
  * @get: Get a reference to an fwnode.
  * @put: Put a reference to an fwnode.
+ * @device_get_match_data: Return the device driver match data.
  * @property_present: Return true if a property is present.
  * @property_read_integer_array: Read an array of integer properties. Return
  *  zero on success, a negative error code
@@ -71,6 +73,8 @@ struct fwnode_operations {
struct fwnode_handle *(*get)(struct fwnode_handle *fwnode);
void (*put)(struct fwnode_handle *fwnode);
bool (*device_is_available)(const struct fwnode_handle *fwnode);
+   void *(*device_get_match_data)(const struct fwnode_handle *fwnode,
+  const struct device *dev);
bool (*property_present)(const struct fwnode_handle *fwnode,
 const char *propname);
int (*property_read_int_array)(const struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..6653ed4 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -275,6 +275,8 @@ int device_add_properties(struct device *dev,
 
 enum dev_dma_attr device_get_dma_attr(struct device *dev);
 
+void *device_get_match_data(struct device *dev);
+
 int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
-- 
1.9.1



[PATCH V8 1/7] Documentation: DT: qcom_hidma: Bump HW revision for the bugfixed HW

2017-12-12 Thread Sinan Kaya
A new version of the HIDMA IP has been released with bug fixes. Bumping the
hardware version to differentiate from others.

Signed-off-by: Sinan Kaya 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt 
b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
index 55492c2..5d93d6d 100644
--- a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
+++ b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
@@ -47,8 +47,8 @@ When the OS is not in control of the management interface 
(i.e. it's a guest),
 the channel nodes appear on their own, not under a management node.
 
 Required properties:
-- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
-for MSI capable HW.
+- compatible: must contain "qcom,hidma-1.0" for initial HW or
+  "qcom,hidma-1.1"/"qcom,hidma-1.2" for MSI capable HW.
 - reg: Addresses for the transfer and event channel
 - interrupts: Should contain the event interrupt
 - desc-count: Number of asynchronous requests this channel can handle
-- 
1.9.1



Re: [PATCH V2 2/3] perf/x86/intel/bm.c: Add Intel Branch Monitoring support

2017-12-12 Thread Peter Zijlstra
On Tue, Dec 12, 2017 at 03:08:00PM -0800, Megha Dey wrote:
> > 
> > There's work on the way to allow multiple HW PMUs. You'll either have to
> > wait for that or help in making that happen. What you do not do is
> > silently hack around it.
> 
> Could I get a pointer to the code implementing this?
> 

There isn't much code now; but it could be build on top of the stuff
here:

  git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git perf/core

It was mostly Mark I think who wanted this for big litte stuffs.


[PATCH V8 1/7] Documentation: DT: qcom_hidma: Bump HW revision for the bugfixed HW

2017-12-12 Thread Sinan Kaya
A new version of the HIDMA IP has been released with bug fixes. Bumping the
hardware version to differentiate from others.

Signed-off-by: Sinan Kaya 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt 
b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
index 55492c2..5d93d6d 100644
--- a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
+++ b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
@@ -47,8 +47,8 @@ When the OS is not in control of the management interface 
(i.e. it's a guest),
 the channel nodes appear on their own, not under a management node.
 
 Required properties:
-- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
-for MSI capable HW.
+- compatible: must contain "qcom,hidma-1.0" for initial HW or
+  "qcom,hidma-1.1"/"qcom,hidma-1.2" for MSI capable HW.
 - reg: Addresses for the transfer and event channel
 - interrupts: Should contain the event interrupt
 - desc-count: Number of asynchronous requests this channel can handle
-- 
1.9.1



Re: [PATCH V2 2/3] perf/x86/intel/bm.c: Add Intel Branch Monitoring support

2017-12-12 Thread Peter Zijlstra
On Tue, Dec 12, 2017 at 03:08:00PM -0800, Megha Dey wrote:
> > 
> > There's work on the way to allow multiple HW PMUs. You'll either have to
> > wait for that or help in making that happen. What you do not do is
> > silently hack around it.
> 
> Could I get a pointer to the code implementing this?
> 

There isn't much code now; but it could be build on top of the stuff
here:

  git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git perf/core

It was mostly Mark I think who wanted this for big litte stuffs.


[PATCH V8 5/7] ACPI: properties: Implement get_match_data() callback

2017-12-12 Thread Sinan Kaya
Now that we have a get_match_data() callback as part of the firmware node,
implement the ACPI specific piece for it.

Signed-off-by: Sinan Kaya 
Acked-by: Sakari Ailus 
---
 drivers/acpi/property.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index e26ea20..466d150 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1271,9 +1271,17 @@ static int acpi_fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
return 0;
 }
 
+static void *
+acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
+ const struct device *dev)
+{
+   return acpi_get_match_data(dev);
+}
+
 #define DECLARE_ACPI_FWNODE_OPS(ops) \
const struct fwnode_operations ops = {  \
.device_is_available = acpi_fwnode_device_is_available, \
+   .device_get_match_data = acpi_fwnode_device_get_match_data, \
.property_present = acpi_fwnode_property_present,   \
.property_read_int_array =  \
acpi_fwnode_property_read_int_array,\
-- 
1.9.1



[PATCH V8 6/7] dmaengine: qcom_hidma: Add support for the new revision

2017-12-12 Thread Sinan Kaya
Add support for probing the newer HW and also organize MSI capable hardware
into an array for maintenance reasons.

Signed-off-by: Sinan Kaya 
---
 drivers/dma/qcom/hidma.c | 34 +-
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index e366985..c146c6d 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -50,6 +50,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,9 @@ static void hidma_free(struct hidma_dev *dmadev)
 module_param(nr_desc_prm, uint, 0644);
 MODULE_PARM_DESC(nr_desc_prm, "number of descriptors (default: 0)");
 
+enum hidma_cap {
+   HIDMA_MSI_CAP = 1,
+};
 
 /* process completed descriptors */
 static void hidma_process_completed(struct hidma_chan *mchan)
@@ -736,25 +740,12 @@ static int hidma_request_msi(struct hidma_dev *dmadev,
 #endif
 }
 
-static bool hidma_msi_capable(struct device *dev)
+static bool hidma_test_capability(struct device *dev, enum hidma_cap test_cap)
 {
-   struct acpi_device *adev = ACPI_COMPANION(dev);
-   const char *of_compat;
-   int ret = -EINVAL;
-
-   if (!adev || acpi_disabled) {
-   ret = device_property_read_string(dev, "compatible",
- _compat);
-   if (ret)
-   return false;
+   enum hidma_cap cap;
 
-   ret = strcmp(of_compat, "qcom,hidma-1.1");
-   } else {
-#ifdef CONFIG_ACPI
-   ret = strcmp(acpi_device_hid(adev), "QCOM8062");
-#endif
-   }
-   return ret == 0;
+   cap = (enum hidma_cap) device_get_match_data(dev);
+   return cap ? ((cap & test_cap) > 0) : 0;
 }
 
 static int hidma_probe(struct platform_device *pdev)
@@ -834,8 +825,7 @@ static int hidma_probe(struct platform_device *pdev)
 * Determine the MSI capability of the platform. Old HW doesn't
 * support MSI.
 */
-   msi = hidma_msi_capable(>dev);
-
+   msi = hidma_test_capability(>dev, HIDMA_MSI_CAP);
device_property_read_u32(>dev, "desc-count",
 >nr_descriptors);
 
@@ -953,7 +943,8 @@ static int hidma_remove(struct platform_device *pdev)
 #if IS_ENABLED(CONFIG_ACPI)
 static const struct acpi_device_id hidma_acpi_ids[] = {
{"QCOM8061"},
-   {"QCOM8062"},
+   {"QCOM8062", HIDMA_MSI_CAP},
+   {"QCOM8063", HIDMA_MSI_CAP},
{},
 };
 MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
@@ -961,7 +952,8 @@ static int hidma_remove(struct platform_device *pdev)
 
 static const struct of_device_id hidma_match[] = {
{.compatible = "qcom,hidma-1.0",},
-   {.compatible = "qcom,hidma-1.1",},
+   {.compatible = "qcom,hidma-1.1", .data = (void *)(HIDMA_MSI_CAP),},
+   {.compatible = "qcom,hidma-1.2", .data = (void *)(HIDMA_MSI_CAP),},
{},
 };
 MODULE_DEVICE_TABLE(of, hidma_match);
-- 
1.9.1



[PATCH V8 5/7] ACPI: properties: Implement get_match_data() callback

2017-12-12 Thread Sinan Kaya
Now that we have a get_match_data() callback as part of the firmware node,
implement the ACPI specific piece for it.

Signed-off-by: Sinan Kaya 
Acked-by: Sakari Ailus 
---
 drivers/acpi/property.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index e26ea20..466d150 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1271,9 +1271,17 @@ static int acpi_fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
return 0;
 }
 
+static void *
+acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
+ const struct device *dev)
+{
+   return acpi_get_match_data(dev);
+}
+
 #define DECLARE_ACPI_FWNODE_OPS(ops) \
const struct fwnode_operations ops = {  \
.device_is_available = acpi_fwnode_device_is_available, \
+   .device_get_match_data = acpi_fwnode_device_get_match_data, \
.property_present = acpi_fwnode_property_present,   \
.property_read_int_array =  \
acpi_fwnode_property_read_int_array,\
-- 
1.9.1



[PATCH V8 6/7] dmaengine: qcom_hidma: Add support for the new revision

2017-12-12 Thread Sinan Kaya
Add support for probing the newer HW and also organize MSI capable hardware
into an array for maintenance reasons.

Signed-off-by: Sinan Kaya 
---
 drivers/dma/qcom/hidma.c | 34 +-
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index e366985..c146c6d 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -50,6 +50,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,9 @@ static void hidma_free(struct hidma_dev *dmadev)
 module_param(nr_desc_prm, uint, 0644);
 MODULE_PARM_DESC(nr_desc_prm, "number of descriptors (default: 0)");
 
+enum hidma_cap {
+   HIDMA_MSI_CAP = 1,
+};
 
 /* process completed descriptors */
 static void hidma_process_completed(struct hidma_chan *mchan)
@@ -736,25 +740,12 @@ static int hidma_request_msi(struct hidma_dev *dmadev,
 #endif
 }
 
-static bool hidma_msi_capable(struct device *dev)
+static bool hidma_test_capability(struct device *dev, enum hidma_cap test_cap)
 {
-   struct acpi_device *adev = ACPI_COMPANION(dev);
-   const char *of_compat;
-   int ret = -EINVAL;
-
-   if (!adev || acpi_disabled) {
-   ret = device_property_read_string(dev, "compatible",
- _compat);
-   if (ret)
-   return false;
+   enum hidma_cap cap;
 
-   ret = strcmp(of_compat, "qcom,hidma-1.1");
-   } else {
-#ifdef CONFIG_ACPI
-   ret = strcmp(acpi_device_hid(adev), "QCOM8062");
-#endif
-   }
-   return ret == 0;
+   cap = (enum hidma_cap) device_get_match_data(dev);
+   return cap ? ((cap & test_cap) > 0) : 0;
 }
 
 static int hidma_probe(struct platform_device *pdev)
@@ -834,8 +825,7 @@ static int hidma_probe(struct platform_device *pdev)
 * Determine the MSI capability of the platform. Old HW doesn't
 * support MSI.
 */
-   msi = hidma_msi_capable(>dev);
-
+   msi = hidma_test_capability(>dev, HIDMA_MSI_CAP);
device_property_read_u32(>dev, "desc-count",
 >nr_descriptors);
 
@@ -953,7 +943,8 @@ static int hidma_remove(struct platform_device *pdev)
 #if IS_ENABLED(CONFIG_ACPI)
 static const struct acpi_device_id hidma_acpi_ids[] = {
{"QCOM8061"},
-   {"QCOM8062"},
+   {"QCOM8062", HIDMA_MSI_CAP},
+   {"QCOM8063", HIDMA_MSI_CAP},
{},
 };
 MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
@@ -961,7 +952,8 @@ static int hidma_remove(struct platform_device *pdev)
 
 static const struct of_device_id hidma_match[] = {
{.compatible = "qcom,hidma-1.0",},
-   {.compatible = "qcom,hidma-1.1",},
+   {.compatible = "qcom,hidma-1.1", .data = (void *)(HIDMA_MSI_CAP),},
+   {.compatible = "qcom,hidma-1.2", .data = (void *)(HIDMA_MSI_CAP),},
{},
 };
 MODULE_DEVICE_TABLE(of, hidma_match);
-- 
1.9.1



[PATCH V8 7/7] dmaengine: qcom_hidma: Add identity register support

2017-12-12 Thread Sinan Kaya
The location for destination event channel register has been relocated from
offset 0x28 to 0x40. Update the code accordingly.

Signed-off-by: Sinan Kaya 
---
 drivers/dma/qcom/hidma.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index c146c6d..963cc52 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -107,6 +107,7 @@ static void hidma_free(struct hidma_dev *dmadev)
 
 enum hidma_cap {
HIDMA_MSI_CAP = 1,
+   HIDMA_IDENTITY_CAP,
 };
 
 /* process completed descriptors */
@@ -838,7 +839,10 @@ static int hidma_probe(struct platform_device *pdev)
if (!dmadev->nr_descriptors)
dmadev->nr_descriptors = HIDMA_NR_DEFAULT_DESC;
 
-   dmadev->chidx = readl(dmadev->dev_trca + 0x28);
+   if (hidma_test_capability(>dev, HIDMA_IDENTITY_CAP))
+   dmadev->chidx = readl(dmadev->dev_trca + 0x40);
+   else
+   dmadev->chidx = readl(dmadev->dev_trca + 0x28);
 
/* Set DMA mask to 64 bits. */
rc = dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(64));
@@ -944,7 +948,7 @@ static int hidma_remove(struct platform_device *pdev)
 static const struct acpi_device_id hidma_acpi_ids[] = {
{"QCOM8061"},
{"QCOM8062", HIDMA_MSI_CAP},
-   {"QCOM8063", HIDMA_MSI_CAP},
+   {"QCOM8063", (HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP)},
{},
 };
 MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
@@ -953,7 +957,8 @@ static int hidma_remove(struct platform_device *pdev)
 static const struct of_device_id hidma_match[] = {
{.compatible = "qcom,hidma-1.0",},
{.compatible = "qcom,hidma-1.1", .data = (void *)(HIDMA_MSI_CAP),},
-   {.compatible = "qcom,hidma-1.2", .data = (void *)(HIDMA_MSI_CAP),},
+   {.compatible = "qcom,hidma-1.2",
+.data = (void *)(HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP),},
{},
 };
 MODULE_DEVICE_TABLE(of, hidma_match);
-- 
1.9.1



[PATCH V8 7/7] dmaengine: qcom_hidma: Add identity register support

2017-12-12 Thread Sinan Kaya
The location for destination event channel register has been relocated from
offset 0x28 to 0x40. Update the code accordingly.

Signed-off-by: Sinan Kaya 
---
 drivers/dma/qcom/hidma.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index c146c6d..963cc52 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -107,6 +107,7 @@ static void hidma_free(struct hidma_dev *dmadev)
 
 enum hidma_cap {
HIDMA_MSI_CAP = 1,
+   HIDMA_IDENTITY_CAP,
 };
 
 /* process completed descriptors */
@@ -838,7 +839,10 @@ static int hidma_probe(struct platform_device *pdev)
if (!dmadev->nr_descriptors)
dmadev->nr_descriptors = HIDMA_NR_DEFAULT_DESC;
 
-   dmadev->chidx = readl(dmadev->dev_trca + 0x28);
+   if (hidma_test_capability(>dev, HIDMA_IDENTITY_CAP))
+   dmadev->chidx = readl(dmadev->dev_trca + 0x40);
+   else
+   dmadev->chidx = readl(dmadev->dev_trca + 0x28);
 
/* Set DMA mask to 64 bits. */
rc = dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(64));
@@ -944,7 +948,7 @@ static int hidma_remove(struct platform_device *pdev)
 static const struct acpi_device_id hidma_acpi_ids[] = {
{"QCOM8061"},
{"QCOM8062", HIDMA_MSI_CAP},
-   {"QCOM8063", HIDMA_MSI_CAP},
+   {"QCOM8063", (HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP)},
{},
 };
 MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
@@ -953,7 +957,8 @@ static int hidma_remove(struct platform_device *pdev)
 static const struct of_device_id hidma_match[] = {
{.compatible = "qcom,hidma-1.0",},
{.compatible = "qcom,hidma-1.1", .data = (void *)(HIDMA_MSI_CAP),},
-   {.compatible = "qcom,hidma-1.2", .data = (void *)(HIDMA_MSI_CAP),},
+   {.compatible = "qcom,hidma-1.2",
+.data = (void *)(HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP),},
{},
 };
 MODULE_DEVICE_TABLE(of, hidma_match);
-- 
1.9.1



[PATCH V8 4/7] OF: properties: Implement get_match_data() callback

2017-12-12 Thread Sinan Kaya
Now that we have a get_match_data() callback as part of the firmware node,
implement the OF specific piece for it.

Signed-off-by: Sinan Kaya 
Reviewed-by: Rob Herring 
Acked-by: Sakari Ailus 
---
 drivers/of/property.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 8ad33a4..f25d363 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -981,10 +981,18 @@ static int of_fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
return 0;
 }
 
+static void *
+of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
+   const struct device *dev)
+{
+   return (void *)of_device_get_match_data(dev);
+}
+
 const struct fwnode_operations of_fwnode_ops = {
.get = of_fwnode_get,
.put = of_fwnode_put,
.device_is_available = of_fwnode_device_is_available,
+   .device_get_match_data = of_fwnode_device_get_match_data,
.property_present = of_fwnode_property_present,
.property_read_int_array = of_fwnode_property_read_int_array,
.property_read_string_array = of_fwnode_property_read_string_array,
-- 
1.9.1



[PATCH V8 4/7] OF: properties: Implement get_match_data() callback

2017-12-12 Thread Sinan Kaya
Now that we have a get_match_data() callback as part of the firmware node,
implement the OF specific piece for it.

Signed-off-by: Sinan Kaya 
Reviewed-by: Rob Herring 
Acked-by: Sakari Ailus 
---
 drivers/of/property.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 8ad33a4..f25d363 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -981,10 +981,18 @@ static int of_fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
return 0;
 }
 
+static void *
+of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
+   const struct device *dev)
+{
+   return (void *)of_device_get_match_data(dev);
+}
+
 const struct fwnode_operations of_fwnode_ops = {
.get = of_fwnode_get,
.put = of_fwnode_put,
.device_is_available = of_fwnode_device_is_available,
+   .device_get_match_data = of_fwnode_device_get_match_data,
.property_present = of_fwnode_property_present,
.property_read_int_array = of_fwnode_property_read_int_array,
.property_read_string_array = of_fwnode_property_read_string_array,
-- 
1.9.1



[PATCH V8 2/7] ACPI / bus: Introduce acpi_get_match_data() function

2017-12-12 Thread Sinan Kaya
OF has of_device_get_match_data() function to extract driver specific data
structure. Add a similar function for ACPI.

Signed-off-by: Sinan Kaya 
Acked-by: Rafael J. Wysocki 
---
 drivers/acpi/bus.c   | 18 ++
 include/linux/acpi.h |  6 ++
 2 files changed, 24 insertions(+)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 4d0979e..f87ed3b 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -785,6 +785,24 @@ const struct acpi_device_id *acpi_match_device(const 
struct acpi_device_id *ids,
 }
 EXPORT_SYMBOL_GPL(acpi_match_device);
 
+void *acpi_get_match_data(const struct device *dev)
+{
+   const struct acpi_device_id *match;
+
+   if (!dev->driver)
+   return NULL;
+
+   if (!dev->driver->acpi_match_table)
+   return NULL;
+
+   match = acpi_match_device(dev->driver->acpi_match_table, dev);
+   if (!match)
+   return NULL;
+
+   return (void *)match->driver_data;
+}
+EXPORT_SYMBOL_GPL(acpi_get_match_data);
+
 int acpi_match_device_ids(struct acpi_device *device,
  const struct acpi_device_id *ids)
 {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index dc1ebfe..9278737 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -584,6 +584,7 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, 
__u64, void *),
 const struct acpi_device_id *acpi_match_device(const struct acpi_device_id 
*ids,
   const struct device *dev);
 
+void *acpi_get_match_data(const struct device *dev);
 extern bool acpi_driver_match_device(struct device *dev,
 const struct device_driver *drv);
 int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
@@ -755,6 +756,11 @@ static inline const struct acpi_device_id 
*acpi_match_device(
return NULL;
 }
 
+static inline void *acpi_get_match_data(const struct device *dev)
+{
+   return NULL;
+}
+
 static inline bool acpi_driver_match_device(struct device *dev,
const struct device_driver *drv)
 {
-- 
1.9.1



[PATCH V8 2/7] ACPI / bus: Introduce acpi_get_match_data() function

2017-12-12 Thread Sinan Kaya
OF has of_device_get_match_data() function to extract driver specific data
structure. Add a similar function for ACPI.

Signed-off-by: Sinan Kaya 
Acked-by: Rafael J. Wysocki 
---
 drivers/acpi/bus.c   | 18 ++
 include/linux/acpi.h |  6 ++
 2 files changed, 24 insertions(+)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 4d0979e..f87ed3b 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -785,6 +785,24 @@ const struct acpi_device_id *acpi_match_device(const 
struct acpi_device_id *ids,
 }
 EXPORT_SYMBOL_GPL(acpi_match_device);
 
+void *acpi_get_match_data(const struct device *dev)
+{
+   const struct acpi_device_id *match;
+
+   if (!dev->driver)
+   return NULL;
+
+   if (!dev->driver->acpi_match_table)
+   return NULL;
+
+   match = acpi_match_device(dev->driver->acpi_match_table, dev);
+   if (!match)
+   return NULL;
+
+   return (void *)match->driver_data;
+}
+EXPORT_SYMBOL_GPL(acpi_get_match_data);
+
 int acpi_match_device_ids(struct acpi_device *device,
  const struct acpi_device_id *ids)
 {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index dc1ebfe..9278737 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -584,6 +584,7 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, 
__u64, void *),
 const struct acpi_device_id *acpi_match_device(const struct acpi_device_id 
*ids,
   const struct device *dev);
 
+void *acpi_get_match_data(const struct device *dev);
 extern bool acpi_driver_match_device(struct device *dev,
 const struct device_driver *drv);
 int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
@@ -755,6 +756,11 @@ static inline const struct acpi_device_id 
*acpi_match_device(
return NULL;
 }
 
+static inline void *acpi_get_match_data(const struct device *dev)
+{
+   return NULL;
+}
+
 static inline bool acpi_driver_match_device(struct device *dev,
const struct device_driver *drv)
 {
-- 
1.9.1



Re: [PATCH -mm] mm, swap: Fix race between swapoff and some swap operations

2017-12-12 Thread Minchan Kim
Hi Huang,
 
Sorry for the late response. I'm in middle of long vacation.

On Fri, Dec 08, 2017 at 08:32:16PM +0800, Huang, Ying wrote:
> Minchan Kim  writes:
> 
> > On Fri, Dec 08, 2017 at 04:41:38PM +0800, Huang, Ying wrote:
> >> Minchan Kim  writes:
> >> 
> >> > On Fri, Dec 08, 2017 at 01:41:10PM +0800, Huang, Ying wrote:
> >> >> Minchan Kim  writes:
> >> >> 
> >> >> > On Thu, Dec 07, 2017 at 04:29:37PM -0800, Andrew Morton wrote:
> >> >> >> On Thu,  7 Dec 2017 09:14:26 +0800 "Huang, Ying" 
> >> >> >>  wrote:
> >> >> >> 
> >> >> >> > When the swapin is performed, after getting the swap entry 
> >> >> >> > information
> >> >> >> > from the page table, the PTL (page table lock) will be released, 
> >> >> >> > then
> >> >> >> > system will go to swap in the swap entry, without any lock held to
> >> >> >> > prevent the swap device from being swapoff.  This may cause the 
> >> >> >> > race
> >> >> >> > like below,
> >> >> >> > 
> >> >> >> > CPU 1  CPU 2
> >> >> >> > -  -
> >> >> >> >do_swap_page
> >> >> >> >  swapin_readahead
> >> >> >> >__read_swap_cache_async
> >> >> >> > swapoff  swapcache_prepare
> >> >> >> >   p->swap_map = NULL   __swap_duplicate
> >> >> >> >  p->swap_map[?] /* !!! NULL 
> >> >> >> > pointer access */
> >> >> >> > 
> >> >> >> > Because swap off is usually done when system shutdown only, the 
> >> >> >> > race
> >> >> >> > may not hit many people in practice.  But it is still a race need 
> >> >> >> > to
> >> >> >> > be fixed.
> >> >> >> 
> >> >> >> swapoff is so rare that it's hard to get motivated about any fix 
> >> >> >> which
> >> >> >> adds overhead to the regular codepaths.
> >> >> >
> >> >> > That was my concern, too when I see this patch.
> >> >> >
> >> >> >> 
> >> >> >> Is there something we can do to ensure that all the overhead of this
> >> >> >> fix is placed into the swapoff side?  stop_machine() may be a bit
> >> >> >> brutal, but a surprising amount of code uses it.  Any other ideas?
> >> >> >
> >> >> > How about this?
> >> >> >
> >> >> > I think It's same approach with old where we uses si->lock everywhere
> >> >> > instead of more fine-grained cluster lock.
> >> >> >
> >> >> > The reason I repeated to reset p->max to zero in the loop is to avoid
> >> >> > using lockdep annotation(maybe, spin_lock_nested(something) to prevent
> >> >> > false positive.
> >> >> >
> >> >> > diff --git a/mm/swapfile.c b/mm/swapfile.c
> >> >> > index 42fe5653814a..9ce007a42bbc 100644
> >> >> > --- a/mm/swapfile.c
> >> >> > +++ b/mm/swapfile.c
> >> >> > @@ -2644,6 +2644,19 @@ SYSCALL_DEFINE1(swapoff, const char __user *, 
> >> >> > specialfile)
> >> >> >   swap_file = p->swap_file;
> >> >> >   old_block_size = p->old_block_size;
> >> >> >   p->swap_file = NULL;
> >> >> > +
> >> >> > + if (p->flags & SWP_SOLIDSTATE) {
> >> >> > + unsigned long ci, nr_cluster;
> >> >> > +
> >> >> > + nr_cluster = DIV_ROUND_UP(p->max, SWAPFILE_CLUSTER);
> >> >> > + for (ci = 0; ci < nr_cluster; ci++) {
> >> >> > + struct swap_cluster_info *sci;
> >> >> > +
> >> >> > + sci = lock_cluster(p, ci * SWAPFILE_CLUSTER);
> >> >> > + p->max = 0;
> >> >> > + unlock_cluster(sci);
> >> >> > + }
> >> >> > + }
> >> >> >   p->max = 0;
> >> >> >   swap_map = p->swap_map;
> >> >> >   p->swap_map = NULL;
> >> >> > @@ -3369,10 +3382,10 @@ static int __swap_duplicate(swp_entry_t 
> >> >> > entry, unsigned char usage)
> >> >> >   goto bad_file;
> >> >> >   p = swap_info[type];
> >> >> >   offset = swp_offset(entry);
> >> >> > - if (unlikely(offset >= p->max))
> >> >> > - goto out;
> >> >> >  
> >> >> >   ci = lock_cluster_or_swap_info(p, offset);
> >> >> > + if (unlikely(offset >= p->max))
> >> >> > + goto unlock_out;
> >> >> >  
> >> >> >   count = p->swap_map[offset];
> >> >> >  
> >> >> 
> >> >> Sorry, this doesn't work, because
> >> >> 
> >> >> lock_cluster_or_swap_info()
> >> >> 
> >> >> Need to read p->cluster_info, which may be freed during swapoff too.
> >> >> 
> >> >> 
> >> >> To reduce the added overhead in regular code path, Maybe we can use SRCU
> >> >> to implement get_swap_device() and put_swap_device()?  There is only
> >> >> increment/decrement on CPU local variable in srcu_read_lock/unlock().
> >> >> Should be acceptable in not so hot swap path?
> >> >> 
> >> >> This needs to select CONFIG_SRCU if CONFIG_SWAP is enabled.  But I guess
> >> >> that should be acceptable too?
> >> >> 
> >> >
> >> > Why do we need srcu here? Is it enough with rcu like below?
> >> >
> >> > It might have a 

Re: [PATCH -mm] mm, swap: Fix race between swapoff and some swap operations

2017-12-12 Thread Minchan Kim
Hi Huang,
 
Sorry for the late response. I'm in middle of long vacation.

On Fri, Dec 08, 2017 at 08:32:16PM +0800, Huang, Ying wrote:
> Minchan Kim  writes:
> 
> > On Fri, Dec 08, 2017 at 04:41:38PM +0800, Huang, Ying wrote:
> >> Minchan Kim  writes:
> >> 
> >> > On Fri, Dec 08, 2017 at 01:41:10PM +0800, Huang, Ying wrote:
> >> >> Minchan Kim  writes:
> >> >> 
> >> >> > On Thu, Dec 07, 2017 at 04:29:37PM -0800, Andrew Morton wrote:
> >> >> >> On Thu,  7 Dec 2017 09:14:26 +0800 "Huang, Ying" 
> >> >> >>  wrote:
> >> >> >> 
> >> >> >> > When the swapin is performed, after getting the swap entry 
> >> >> >> > information
> >> >> >> > from the page table, the PTL (page table lock) will be released, 
> >> >> >> > then
> >> >> >> > system will go to swap in the swap entry, without any lock held to
> >> >> >> > prevent the swap device from being swapoff.  This may cause the 
> >> >> >> > race
> >> >> >> > like below,
> >> >> >> > 
> >> >> >> > CPU 1  CPU 2
> >> >> >> > -  -
> >> >> >> >do_swap_page
> >> >> >> >  swapin_readahead
> >> >> >> >__read_swap_cache_async
> >> >> >> > swapoff  swapcache_prepare
> >> >> >> >   p->swap_map = NULL   __swap_duplicate
> >> >> >> >  p->swap_map[?] /* !!! NULL 
> >> >> >> > pointer access */
> >> >> >> > 
> >> >> >> > Because swap off is usually done when system shutdown only, the 
> >> >> >> > race
> >> >> >> > may not hit many people in practice.  But it is still a race need 
> >> >> >> > to
> >> >> >> > be fixed.
> >> >> >> 
> >> >> >> swapoff is so rare that it's hard to get motivated about any fix 
> >> >> >> which
> >> >> >> adds overhead to the regular codepaths.
> >> >> >
> >> >> > That was my concern, too when I see this patch.
> >> >> >
> >> >> >> 
> >> >> >> Is there something we can do to ensure that all the overhead of this
> >> >> >> fix is placed into the swapoff side?  stop_machine() may be a bit
> >> >> >> brutal, but a surprising amount of code uses it.  Any other ideas?
> >> >> >
> >> >> > How about this?
> >> >> >
> >> >> > I think It's same approach with old where we uses si->lock everywhere
> >> >> > instead of more fine-grained cluster lock.
> >> >> >
> >> >> > The reason I repeated to reset p->max to zero in the loop is to avoid
> >> >> > using lockdep annotation(maybe, spin_lock_nested(something) to prevent
> >> >> > false positive.
> >> >> >
> >> >> > diff --git a/mm/swapfile.c b/mm/swapfile.c
> >> >> > index 42fe5653814a..9ce007a42bbc 100644
> >> >> > --- a/mm/swapfile.c
> >> >> > +++ b/mm/swapfile.c
> >> >> > @@ -2644,6 +2644,19 @@ SYSCALL_DEFINE1(swapoff, const char __user *, 
> >> >> > specialfile)
> >> >> >   swap_file = p->swap_file;
> >> >> >   old_block_size = p->old_block_size;
> >> >> >   p->swap_file = NULL;
> >> >> > +
> >> >> > + if (p->flags & SWP_SOLIDSTATE) {
> >> >> > + unsigned long ci, nr_cluster;
> >> >> > +
> >> >> > + nr_cluster = DIV_ROUND_UP(p->max, SWAPFILE_CLUSTER);
> >> >> > + for (ci = 0; ci < nr_cluster; ci++) {
> >> >> > + struct swap_cluster_info *sci;
> >> >> > +
> >> >> > + sci = lock_cluster(p, ci * SWAPFILE_CLUSTER);
> >> >> > + p->max = 0;
> >> >> > + unlock_cluster(sci);
> >> >> > + }
> >> >> > + }
> >> >> >   p->max = 0;
> >> >> >   swap_map = p->swap_map;
> >> >> >   p->swap_map = NULL;
> >> >> > @@ -3369,10 +3382,10 @@ static int __swap_duplicate(swp_entry_t 
> >> >> > entry, unsigned char usage)
> >> >> >   goto bad_file;
> >> >> >   p = swap_info[type];
> >> >> >   offset = swp_offset(entry);
> >> >> > - if (unlikely(offset >= p->max))
> >> >> > - goto out;
> >> >> >  
> >> >> >   ci = lock_cluster_or_swap_info(p, offset);
> >> >> > + if (unlikely(offset >= p->max))
> >> >> > + goto unlock_out;
> >> >> >  
> >> >> >   count = p->swap_map[offset];
> >> >> >  
> >> >> 
> >> >> Sorry, this doesn't work, because
> >> >> 
> >> >> lock_cluster_or_swap_info()
> >> >> 
> >> >> Need to read p->cluster_info, which may be freed during swapoff too.
> >> >> 
> >> >> 
> >> >> To reduce the added overhead in regular code path, Maybe we can use SRCU
> >> >> to implement get_swap_device() and put_swap_device()?  There is only
> >> >> increment/decrement on CPU local variable in srcu_read_lock/unlock().
> >> >> Should be acceptable in not so hot swap path?
> >> >> 
> >> >> This needs to select CONFIG_SRCU if CONFIG_SWAP is enabled.  But I guess
> >> >> that should be acceptable too?
> >> >> 
> >> >
> >> > Why do we need srcu here? Is it enough with rcu like below?
> >> >
> >> > It might have a bug/room to be optimized about performance/naming.
> >> > I just wanted to show my 

Re: [PATCH] iommu/vt-d: Fix shift overflow in qi_flush_dev_iotlb

2017-12-12 Thread Peter Xu
On Tue, Dec 12, 2017 at 03:43:08PM -0700, Alex Williamson wrote:

[...]

> diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
> index 9a7ffd13c7f0..87888b102057 100644
> --- a/drivers/iommu/dmar.c
> +++ b/drivers/iommu/dmar.c
> @@ -1345,7 +1345,9 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 
> sid, u16 qdep,
>   struct qi_desc desc;
>  
>   if (mask) {
> - BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
> + BUG_ON((mask > MAX_AGAW_PFN_WIDTH) ||
> +((mask == MAX_AGAW_PFN_WIDTH) && addr) ||
> +(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1)));

Could it work if we just use 1ULL instead of 1 here?  Thanks,

-- 
Peter Xu


Re: [PATCH] iommu/vt-d: Fix shift overflow in qi_flush_dev_iotlb

2017-12-12 Thread Peter Xu
On Tue, Dec 12, 2017 at 03:43:08PM -0700, Alex Williamson wrote:

[...]

> diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
> index 9a7ffd13c7f0..87888b102057 100644
> --- a/drivers/iommu/dmar.c
> +++ b/drivers/iommu/dmar.c
> @@ -1345,7 +1345,9 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 
> sid, u16 qdep,
>   struct qi_desc desc;
>  
>   if (mask) {
> - BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
> + BUG_ON((mask > MAX_AGAW_PFN_WIDTH) ||
> +((mask == MAX_AGAW_PFN_WIDTH) && addr) ||
> +(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1)));

Could it work if we just use 1ULL instead of 1 here?  Thanks,

-- 
Peter Xu


Re: About the try to remove cross-release feature entirely by Ingo

2017-12-12 Thread Byungchul Park
On Wed, Dec 13, 2017 at 3:24 PM, Byungchul Park
 wrote:
> Lockdep works, based on the following:
>
>(1) Classifying locks properly
>(2) Checking relationship between the classes
>
> If (1) is not good or (2) is not good, then we
> might get false positives.
>
> For (1), we don't have to classify locks 100%
> properly but need as enough as lockdep works.
>
> For (2), we should have a mechanism w/o
> logical defects.
>
> Cross-release added an additional capacity to
> (2) and requires (1) to get more precisely classified.
>
> Since the current classification level is too low for
> cross-release to work, false positives are being
> reported frequently with enabling cross-release.
> Yes. It's a obvious problem. It needs to be off by
> default until the classification is done by the level
> that cross-release requires.
>
> But, the logic (2) is valid and logically true. Please
> keep the code, mechanism, and logic.

In addition, I want to say that the current level of
classification is much less than 100% but, since we
have annotated well to suppress wrong reports by
rough classifications, finally it does not come into
view by original lockdep for now.

But since cross-release makes the dependency
graph more fine-grained, it easily comes into view.

Even w/o cross-release, it can happen by adding
additional dependencies connecting two roughly
classified lock classes in the future.

Furthermore, I can see many places in kernel to
consider wait_for_completion() using manual
lock_acquire()/lock_release() and the rate using it
raises.

In other words, even without cross-release, the
more we add manual annotations for
wait_for_completion() the more we definitely
suffer same problems someday, we are facing now
through cross-release.

Therefore, I want to say the fundamental problem
comes from classification, not cross-release
specific. Of course, since cross-release accelerates
the condition, I agree with it to be off for now.

-- 
Thanks,
Byungchul


Re: About the try to remove cross-release feature entirely by Ingo

2017-12-12 Thread Byungchul Park
On Wed, Dec 13, 2017 at 3:24 PM, Byungchul Park
 wrote:
> Lockdep works, based on the following:
>
>(1) Classifying locks properly
>(2) Checking relationship between the classes
>
> If (1) is not good or (2) is not good, then we
> might get false positives.
>
> For (1), we don't have to classify locks 100%
> properly but need as enough as lockdep works.
>
> For (2), we should have a mechanism w/o
> logical defects.
>
> Cross-release added an additional capacity to
> (2) and requires (1) to get more precisely classified.
>
> Since the current classification level is too low for
> cross-release to work, false positives are being
> reported frequently with enabling cross-release.
> Yes. It's a obvious problem. It needs to be off by
> default until the classification is done by the level
> that cross-release requires.
>
> But, the logic (2) is valid and logically true. Please
> keep the code, mechanism, and logic.

In addition, I want to say that the current level of
classification is much less than 100% but, since we
have annotated well to suppress wrong reports by
rough classifications, finally it does not come into
view by original lockdep for now.

But since cross-release makes the dependency
graph more fine-grained, it easily comes into view.

Even w/o cross-release, it can happen by adding
additional dependencies connecting two roughly
classified lock classes in the future.

Furthermore, I can see many places in kernel to
consider wait_for_completion() using manual
lock_acquire()/lock_release() and the rate using it
raises.

In other words, even without cross-release, the
more we add manual annotations for
wait_for_completion() the more we definitely
suffer same problems someday, we are facing now
through cross-release.

Therefore, I want to say the fundamental problem
comes from classification, not cross-release
specific. Of course, since cross-release accelerates
the condition, I agree with it to be off for now.

-- 
Thanks,
Byungchul


[PATCH v3] perf evsel: Enable ignore_missing_thread for pid option

2017-12-12 Thread Mengting Zhang
While monitoring a multithread process with pid option, perf sometimes
may return sys_perf_event_open failure with 3(No such process) if any
of the process's threads die before we open the event. However, we want
perf continue monitoring the remaining threads and do not exit with error.

Here, the patch enables perf_evsel::ignore_missing_thread for -p option
to ignore complete failure if any of threads die before we open the event.
But it may still return sys_perf_event_open failure with 22(Invalid) if we
monitors several event groups.

sys_perf_event_open: pid 28960  cpu 40  group_fd 118202  flags 0x8
sys_perf_event_open: pid 28961  cpu 40  group_fd 118203  flags 0x8
WARNING: Ignored open failure for pid 28962
sys_perf_event_open: pid 28962  cpu 40  group_fd [118203]  flags 0x8
sys_perf_event_open failed, error -22

That is because when we ignore a missing thread, we change the thread_idx
without dealing with its fds, FD(evsel, cpu, thread). Then get_group_fd()
may return a wrong group_fd for the next thread and sys_perf_event_open()
return with 22.

sys_perf_event_open(){
   ...
   if (group_fd != -1)
   perf_fget_light()//to get corresponding group_leader by group_fd
   ...
   if (group_leader)
  if (group_leader->ctx->task != ctx->task)//should on the same task
   goto err_context
   ...
}

This patch also fixes this bug by introducing perf_evsel__remove_fd() and
update_fds to allow removing fds for the missing thread.

Changes since v1:
- Change group_fd__remove() into a more genetic way without changing code logic
- Remove redundant condition

Changes since v2:
- Use a proper function name and add some comment.
- Multiline comment style fixes.

Signed-off-by: Mengting Zhang 
---
 tools/perf/builtin-record.c |  4 ++--
 tools/perf/util/evsel.c | 48 +++--
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0032559..36b6213 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1781,8 +1781,8 @@ int cmd_record(int argc, const char **argv)
goto out;
}
 
-   /* Enable ignoring missing threads when -u option is defined. */
-   rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX;
+   /* Enable ignoring missing threads when -u/-p option is defined. */
+   rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || 
rec->opts.target.pid;
 
err = -ENOMEM;
if (perf_evlist__create_maps(rec->evlist, >opts.target) < 0)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d5fbcf8..a0a3df7 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1596,10 +1596,47 @@ static int __open_attr__fprintf(FILE *fp, const char 
*name, const char *val,
return fprintf(fp, "  %-32s %s\n", name, val);
 }
 
+static void perf_evsel__remove_fd(struct perf_evsel *pos,
+ int nr_cpus, int nr_threads,
+ int thread_idx)
+{
+   for (int cpu = 0; cpu < nr_cpus; cpu++)
+   for (int thread = thread_idx; thread < nr_threads - 1; thread++)
+   FD(pos, cpu, thread) = FD(pos, cpu, thread + 1);
+}
+
+static int update_fds(struct perf_evsel *evsel,
+ int nr_cpus, int cpu_idx,
+ int nr_threads, int thread_idx)
+{
+   struct perf_evsel *pos;
+   struct perf_evlist *evlist = evsel->evlist;
+
+   if (cpu_idx >= nr_cpus || thread_idx >= nr_threads)
+   return -EINVAL;
+
+   evlist__for_each_entry(evlist, pos) {
+   nr_cpus = pos != evsel ? nr_cpus : cpu_idx;
+
+   perf_evsel__remove_fd(pos, nr_cpus, nr_threads, thread_idx);
+
+   /*
+* Since fds for next evsel has not been created,
+* there is no need to iterate whole event list.
+*/
+   if (pos == evsel)
+   break;
+   }
+   return 0;
+}
+
 static bool ignore_missing_thread(struct perf_evsel *evsel,
+ int nr_cpus, int cpu,
  struct thread_map *threads,
  int thread, int err)
 {
+   pid_t ignore_pid = thread_map__pid(threads, thread);
+
if (!evsel->ignore_missing_thread)
return false;
 
@@ -1615,11 +1652,18 @@ static bool ignore_missing_thread(struct perf_evsel 
*evsel,
if (threads->nr == 1)
return false;
 
+   /*
+* We should remove fd for missing_thread first
+* because thread_map__remove() will decrease threads->nr.
+*/
+   if (update_fds(evsel, nr_cpus, cpu, threads->nr, thread))
+   return false;
+
   

[PATCH v3] perf evsel: Enable ignore_missing_thread for pid option

2017-12-12 Thread Mengting Zhang
While monitoring a multithread process with pid option, perf sometimes
may return sys_perf_event_open failure with 3(No such process) if any
of the process's threads die before we open the event. However, we want
perf continue monitoring the remaining threads and do not exit with error.

Here, the patch enables perf_evsel::ignore_missing_thread for -p option
to ignore complete failure if any of threads die before we open the event.
But it may still return sys_perf_event_open failure with 22(Invalid) if we
monitors several event groups.

sys_perf_event_open: pid 28960  cpu 40  group_fd 118202  flags 0x8
sys_perf_event_open: pid 28961  cpu 40  group_fd 118203  flags 0x8
WARNING: Ignored open failure for pid 28962
sys_perf_event_open: pid 28962  cpu 40  group_fd [118203]  flags 0x8
sys_perf_event_open failed, error -22

That is because when we ignore a missing thread, we change the thread_idx
without dealing with its fds, FD(evsel, cpu, thread). Then get_group_fd()
may return a wrong group_fd for the next thread and sys_perf_event_open()
return with 22.

sys_perf_event_open(){
   ...
   if (group_fd != -1)
   perf_fget_light()//to get corresponding group_leader by group_fd
   ...
   if (group_leader)
  if (group_leader->ctx->task != ctx->task)//should on the same task
   goto err_context
   ...
}

This patch also fixes this bug by introducing perf_evsel__remove_fd() and
update_fds to allow removing fds for the missing thread.

Changes since v1:
- Change group_fd__remove() into a more genetic way without changing code logic
- Remove redundant condition

Changes since v2:
- Use a proper function name and add some comment.
- Multiline comment style fixes.

Signed-off-by: Mengting Zhang 
---
 tools/perf/builtin-record.c |  4 ++--
 tools/perf/util/evsel.c | 48 +++--
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0032559..36b6213 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1781,8 +1781,8 @@ int cmd_record(int argc, const char **argv)
goto out;
}
 
-   /* Enable ignoring missing threads when -u option is defined. */
-   rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX;
+   /* Enable ignoring missing threads when -u/-p option is defined. */
+   rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || 
rec->opts.target.pid;
 
err = -ENOMEM;
if (perf_evlist__create_maps(rec->evlist, >opts.target) < 0)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d5fbcf8..a0a3df7 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1596,10 +1596,47 @@ static int __open_attr__fprintf(FILE *fp, const char 
*name, const char *val,
return fprintf(fp, "  %-32s %s\n", name, val);
 }
 
+static void perf_evsel__remove_fd(struct perf_evsel *pos,
+ int nr_cpus, int nr_threads,
+ int thread_idx)
+{
+   for (int cpu = 0; cpu < nr_cpus; cpu++)
+   for (int thread = thread_idx; thread < nr_threads - 1; thread++)
+   FD(pos, cpu, thread) = FD(pos, cpu, thread + 1);
+}
+
+static int update_fds(struct perf_evsel *evsel,
+ int nr_cpus, int cpu_idx,
+ int nr_threads, int thread_idx)
+{
+   struct perf_evsel *pos;
+   struct perf_evlist *evlist = evsel->evlist;
+
+   if (cpu_idx >= nr_cpus || thread_idx >= nr_threads)
+   return -EINVAL;
+
+   evlist__for_each_entry(evlist, pos) {
+   nr_cpus = pos != evsel ? nr_cpus : cpu_idx;
+
+   perf_evsel__remove_fd(pos, nr_cpus, nr_threads, thread_idx);
+
+   /*
+* Since fds for next evsel has not been created,
+* there is no need to iterate whole event list.
+*/
+   if (pos == evsel)
+   break;
+   }
+   return 0;
+}
+
 static bool ignore_missing_thread(struct perf_evsel *evsel,
+ int nr_cpus, int cpu,
  struct thread_map *threads,
  int thread, int err)
 {
+   pid_t ignore_pid = thread_map__pid(threads, thread);
+
if (!evsel->ignore_missing_thread)
return false;
 
@@ -1615,11 +1652,18 @@ static bool ignore_missing_thread(struct perf_evsel 
*evsel,
if (threads->nr == 1)
return false;
 
+   /*
+* We should remove fd for missing_thread first
+* because thread_map__remove() will decrease threads->nr.
+*/
+   if (update_fds(evsel, nr_cpus, cpu, threads->nr, thread))
+   return false;
+
if 

Re: [PATCH] vfio: Simplify capability helper

2017-12-12 Thread Zhenyu Wang
On 2017.12.13 12:13:34 +1100, Alexey Kardashevskiy wrote:
> On 13/12/17 06:59, Alex Williamson wrote:
> > The vfio_info_add_capability() helper requires the caller to pass a
> > capability ID, which it then uses to fill in header fields, assuming
> > hard coded versions.  This makes for an awkward and rigid interface.
> > The only thing we want this helper to do is allocate sufficient
> > space in the caps buffer and chain this capability into the list.
> > Reduce it to that simple task.
> > 
> > Signed-off-by: Alex Williamson 
> 
> 
> Makes more sense now, thanks. I'll repost mine on top of this.
> 
> 
> Reviewed-by: Alexey Kardashevskiy 
> 
>

Looks good for KVMGT part.

Acked-by: Zhenyu Wang 

> Below one observation, unrelated to this patch.
> 
> > ---
> >  drivers/gpu/drm/i915/gvt/kvmgt.c |   15 +++
> >  drivers/vfio/pci/vfio_pci.c  |   14 ++
> >  drivers/vfio/vfio.c  |   52 
> > +++---
> >  include/linux/vfio.h |3 +-
> >  4 files changed, 24 insertions(+), 60 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c 
> > b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > index 96060920a6fe..0a7d084da1a2 100644
> > --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > @@ -1012,6 +1012,8 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > if (!sparse)
> > return -ENOMEM;
> >  
> > +   sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
> > +   sparse->header.version = 1;
> > sparse->nr_areas = nr_areas;
> > cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
> 
> 
> @cap_type_id is initialized in just one of many cases of switch
> (info.index) and after the entire switch, there is switch (cap_type_id). I
> wonder why compiler missed "potentially uninitialized variable here,
> although there is no bug - @cap_type_id is in sync with @spapse. It would
> make it cleaner imho just to have vfio_info_add_capability() next to the
> header initialization.
> 

yeah, we could clean that up, thanks for pointing out.

> 
> 
> > sparse->areas[0].offset =
> > @@ -1033,7 +1035,9 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > break;
> > default:
> > {
> > -   struct vfio_region_info_cap_type cap_type;
> > +   struct vfio_region_info_cap_type cap_type = {
> > +   .header.id = VFIO_REGION_INFO_CAP_TYPE,
> > +   .header.version = 1 };
> >  
> > if (info.index >= VFIO_PCI_NUM_REGIONS +
> > vgpu->vdev.num_regions)
> > @@ -1050,8 +1054,8 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > cap_type.subtype = vgpu->vdev.region[i].subtype;
> >  
> > ret = vfio_info_add_capability(,
> > -   VFIO_REGION_INFO_CAP_TYPE,
> > -   _type);
> > +   _type.header,
> > +   sizeof(cap_type));
> > if (ret)
> > return ret;
> > }
> > @@ -1061,8 +1065,9 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > switch (cap_type_id) {
> > case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
> > ret = vfio_info_add_capability(,
> > -   VFIO_REGION_INFO_CAP_SPARSE_MMAP,
> > -   sparse);
> > +   >header, sizeof(*sparse) +
> > +   (sparse->nr_areas *
> > +   sizeof(*sparse->areas)));
> > kfree(sparse);
> > if (ret)
> > return ret;
> > diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
> > index f041b1a6cf66..a73e40983880 100644
> > --- a/drivers/vfio/pci/vfio_pci.c
> > +++ b/drivers/vfio/pci/vfio_pci.c
> > @@ -582,6 +582,8 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device 
> > *vdev,
> > if (!sparse)
> > return -ENOMEM;
> >  
> > +   sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
> > +   sparse->header.version = 1;
> > sparse->nr_areas = nr_areas;
> >  
> > if (vdev->msix_offset & PAGE_MASK) {
> > @@ -597,8 +599,7 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device 
> > *vdev,
> > i++;

Re: [PATCH] vfio: Simplify capability helper

2017-12-12 Thread Zhenyu Wang
On 2017.12.13 12:13:34 +1100, Alexey Kardashevskiy wrote:
> On 13/12/17 06:59, Alex Williamson wrote:
> > The vfio_info_add_capability() helper requires the caller to pass a
> > capability ID, which it then uses to fill in header fields, assuming
> > hard coded versions.  This makes for an awkward and rigid interface.
> > The only thing we want this helper to do is allocate sufficient
> > space in the caps buffer and chain this capability into the list.
> > Reduce it to that simple task.
> > 
> > Signed-off-by: Alex Williamson 
> 
> 
> Makes more sense now, thanks. I'll repost mine on top of this.
> 
> 
> Reviewed-by: Alexey Kardashevskiy 
> 
>

Looks good for KVMGT part.

Acked-by: Zhenyu Wang 

> Below one observation, unrelated to this patch.
> 
> > ---
> >  drivers/gpu/drm/i915/gvt/kvmgt.c |   15 +++
> >  drivers/vfio/pci/vfio_pci.c  |   14 ++
> >  drivers/vfio/vfio.c  |   52 
> > +++---
> >  include/linux/vfio.h |3 +-
> >  4 files changed, 24 insertions(+), 60 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c 
> > b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > index 96060920a6fe..0a7d084da1a2 100644
> > --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > @@ -1012,6 +1012,8 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > if (!sparse)
> > return -ENOMEM;
> >  
> > +   sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
> > +   sparse->header.version = 1;
> > sparse->nr_areas = nr_areas;
> > cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
> 
> 
> @cap_type_id is initialized in just one of many cases of switch
> (info.index) and after the entire switch, there is switch (cap_type_id). I
> wonder why compiler missed "potentially uninitialized variable here,
> although there is no bug - @cap_type_id is in sync with @spapse. It would
> make it cleaner imho just to have vfio_info_add_capability() next to the
> header initialization.
> 

yeah, we could clean that up, thanks for pointing out.

> 
> 
> > sparse->areas[0].offset =
> > @@ -1033,7 +1035,9 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > break;
> > default:
> > {
> > -   struct vfio_region_info_cap_type cap_type;
> > +   struct vfio_region_info_cap_type cap_type = {
> > +   .header.id = VFIO_REGION_INFO_CAP_TYPE,
> > +   .header.version = 1 };
> >  
> > if (info.index >= VFIO_PCI_NUM_REGIONS +
> > vgpu->vdev.num_regions)
> > @@ -1050,8 +1054,8 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > cap_type.subtype = vgpu->vdev.region[i].subtype;
> >  
> > ret = vfio_info_add_capability(,
> > -   VFIO_REGION_INFO_CAP_TYPE,
> > -   _type);
> > +   _type.header,
> > +   sizeof(cap_type));
> > if (ret)
> > return ret;
> > }
> > @@ -1061,8 +1065,9 @@ static long intel_vgpu_ioctl(struct mdev_device 
> > *mdev, unsigned int cmd,
> > switch (cap_type_id) {
> > case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
> > ret = vfio_info_add_capability(,
> > -   VFIO_REGION_INFO_CAP_SPARSE_MMAP,
> > -   sparse);
> > +   >header, sizeof(*sparse) +
> > +   (sparse->nr_areas *
> > +   sizeof(*sparse->areas)));
> > kfree(sparse);
> > if (ret)
> > return ret;
> > diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
> > index f041b1a6cf66..a73e40983880 100644
> > --- a/drivers/vfio/pci/vfio_pci.c
> > +++ b/drivers/vfio/pci/vfio_pci.c
> > @@ -582,6 +582,8 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device 
> > *vdev,
> > if (!sparse)
> > return -ENOMEM;
> >  
> > +   sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
> > +   sparse->header.version = 1;
> > sparse->nr_areas = nr_areas;
> >  
> > if (vdev->msix_offset & PAGE_MASK) {
> > @@ -597,8 +599,7 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device 
> > *vdev,
> > i++;
> > }
> >  
> > -   ret = vfio_info_add_capability(caps, 

[PATCH] KVM: arm/arm64: don't set vtimer->cnt_ctl in kvm_arch_timer_handler

2017-12-12 Thread Jia He
In our Armv8a server (qualcomm Amberwing, non VHE), after applying
Christoffer's timer optimizing patchset(Optimize arch timer register
handling), the guest is hang during kernel booting.

The error root cause might be as follows:
1. in kvm_arch_timer_handler, it reset vtimer->cnt_ctl with current
cntv_ctl register value. And then it missed some cases to update timer's
irq (irq.level) when kvm_timer_irq_can_fire() is false
2. It causes kvm_vcpu_check_block return 0 instead of -EINTR
kvm_vcpu_check_block
kvm_cpu_has_pending_timer
kvm_timer_is_pending
kvm_timer_should_fire
3. Thus, the kvm hyp code can not break the loop in kvm_vcpu_block (halt
poll process) and the guest is hang forever

Fixes: b103cc3f10c0 ("KVM: arm/arm64: Avoid timer save/restore in vcpu 
entry/exit")
Signed-off-by: Jia He 
---
 virt/kvm/arm/arch_timer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index f9555b1..bb86433 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -100,7 +100,6 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void 
*dev_id)
vtimer = vcpu_vtimer(vcpu);
 
if (!vtimer->irq.level) {
-   vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
if (kvm_timer_irq_can_fire(vtimer))
kvm_timer_update_irq(vcpu, true, vtimer);
}
-- 
2.7.4



[PATCH] KVM: arm/arm64: don't set vtimer->cnt_ctl in kvm_arch_timer_handler

2017-12-12 Thread Jia He
In our Armv8a server (qualcomm Amberwing, non VHE), after applying
Christoffer's timer optimizing patchset(Optimize arch timer register
handling), the guest is hang during kernel booting.

The error root cause might be as follows:
1. in kvm_arch_timer_handler, it reset vtimer->cnt_ctl with current
cntv_ctl register value. And then it missed some cases to update timer's
irq (irq.level) when kvm_timer_irq_can_fire() is false
2. It causes kvm_vcpu_check_block return 0 instead of -EINTR
kvm_vcpu_check_block
kvm_cpu_has_pending_timer
kvm_timer_is_pending
kvm_timer_should_fire
3. Thus, the kvm hyp code can not break the loop in kvm_vcpu_block (halt
poll process) and the guest is hang forever

Fixes: b103cc3f10c0 ("KVM: arm/arm64: Avoid timer save/restore in vcpu 
entry/exit")
Signed-off-by: Jia He 
---
 virt/kvm/arm/arch_timer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index f9555b1..bb86433 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -100,7 +100,6 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void 
*dev_id)
vtimer = vcpu_vtimer(vcpu);
 
if (!vtimer->irq.level) {
-   vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
if (kvm_timer_irq_can_fire(vtimer))
kvm_timer_update_irq(vcpu, true, vtimer);
}
-- 
2.7.4



[v3 PATCH 0/3] powernv-cpufreq: Multiple pstate related fixes.

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

 This is a third version of the patch to fix pstate related issues in
 the powernv-cpufreq driver.

 The previous versions can be found here:
 [v2]: https://lkml.org/lkml/2017/12/7/1562
 [v1]: https://lkml.org/lkml/2017/11/29/1338

 On POWERNV platform, Pstates are 8-bit values. On POWER8 they are
 negatively numbered while on POWER9 they are positively
 numbered. Thus, on POWER9, the maximum number of pstates could be as
 high as 256.

 In multiple places, the current code interprets pstates as a signed
 8-bit value which subsequently gets assigned to a signed integer
 variable. This causes a problem on POWER9 platforms which have more
 than 128 pstates.  On such systems, on a CPU that is in a lower
 pstate whose number is greater than 128, querying the current pstate
 via the pstate_to_idx() returns a "pstate X is out of bound" error
 message and the current pstate is reported as the nominal
 pstate. This is due to the manner in which the bounds are checked in
 pstate_to_idx which again depends on the sign of pstates and whether
 the pstates max to min are monotonically increasing or decreasing.

 Further the current code makes a couple of assumptions which is not
 guaranteed by the device-tree bindings:

  1) Pstate ids are continguous.

  2) Every Pstate should always lie between the max and the min
 pstates that are explicitly reported in the device tree.

Both these assumptions are unwarranted and can change on future
platforms.

In this patch-series, we fix the implementation via the following
changes:

PATCH 1: Define a helper function to correctly extract the pstates
 from the PMCR and take care of any sign extentions. This is
 an immediate fix to add the ability to handle more than 128
 pstates on POWER9 systems.

PATCH 2: Define a hash-map which will return the index into the
 cpufreq frequency table for a given pstate. Use this hashmap
 in the implementation of pstate_to_idx(). This does away with
 the assumptions (1) mentioned above, and will work with non
 continguous pstate ids. If no entry exists for a particular
 pstate, then such a pstate is treated as being out of
 bounds. This gets rid of assumption (2).

PATCH 3: Treat pstates as opaque 8-bit values consistent with the
 definitions in the PMSR and PMCR. We no longer need any
 sign-extentions nor do we require to interpret the sign of
 the pstates anywhere in the code.


Gautham R. Shenoy (3):
  powernv-cpufreq: Add helper to extract pstate from PMSR
  powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates
  powernv-cpufreq: Treat pstates as opaque 8-bit values

 drivers/cpufreq/powernv-cpufreq.c | 139 --
 1 file changed, 90 insertions(+), 49 deletions(-)

-- 
1.9.4



[v3 PATCH 0/3] powernv-cpufreq: Multiple pstate related fixes.

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

 This is a third version of the patch to fix pstate related issues in
 the powernv-cpufreq driver.

 The previous versions can be found here:
 [v2]: https://lkml.org/lkml/2017/12/7/1562
 [v1]: https://lkml.org/lkml/2017/11/29/1338

 On POWERNV platform, Pstates are 8-bit values. On POWER8 they are
 negatively numbered while on POWER9 they are positively
 numbered. Thus, on POWER9, the maximum number of pstates could be as
 high as 256.

 In multiple places, the current code interprets pstates as a signed
 8-bit value which subsequently gets assigned to a signed integer
 variable. This causes a problem on POWER9 platforms which have more
 than 128 pstates.  On such systems, on a CPU that is in a lower
 pstate whose number is greater than 128, querying the current pstate
 via the pstate_to_idx() returns a "pstate X is out of bound" error
 message and the current pstate is reported as the nominal
 pstate. This is due to the manner in which the bounds are checked in
 pstate_to_idx which again depends on the sign of pstates and whether
 the pstates max to min are monotonically increasing or decreasing.

 Further the current code makes a couple of assumptions which is not
 guaranteed by the device-tree bindings:

  1) Pstate ids are continguous.

  2) Every Pstate should always lie between the max and the min
 pstates that are explicitly reported in the device tree.

Both these assumptions are unwarranted and can change on future
platforms.

In this patch-series, we fix the implementation via the following
changes:

PATCH 1: Define a helper function to correctly extract the pstates
 from the PMCR and take care of any sign extentions. This is
 an immediate fix to add the ability to handle more than 128
 pstates on POWER9 systems.

PATCH 2: Define a hash-map which will return the index into the
 cpufreq frequency table for a given pstate. Use this hashmap
 in the implementation of pstate_to_idx(). This does away with
 the assumptions (1) mentioned above, and will work with non
 continguous pstate ids. If no entry exists for a particular
 pstate, then such a pstate is treated as being out of
 bounds. This gets rid of assumption (2).

PATCH 3: Treat pstates as opaque 8-bit values consistent with the
 definitions in the PMSR and PMCR. We no longer need any
 sign-extentions nor do we require to interpret the sign of
 the pstates anywhere in the code.


Gautham R. Shenoy (3):
  powernv-cpufreq: Add helper to extract pstate from PMSR
  powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates
  powernv-cpufreq: Treat pstates as opaque 8-bit values

 drivers/cpufreq/powernv-cpufreq.c | 139 --
 1 file changed, 90 insertions(+), 49 deletions(-)

-- 
1.9.4



[v3 PATCH 2/3] powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

The code in powernv-cpufreq, makes the following two assumptions which
are not guaranteed by the device-tree bindings:

1) Pstate ids are continguous: This is used in pstate_to_idx() to
   obtain the reverse map from a pstate to it's corresponding
   entry into the cpufreq frequency table.

2) Every Pstate should always lie between the max and the min
   pstates that are explicitly reported in the device tree: This
   is used to determine whether a pstate reported by the PMSR is
   out of bounds.

Both these assumptions are unwarranted and can change on future
platforms.

In this patch, we maintain the reverse map from a pstate to it's index
in the cpufreq frequency table and use this in pstate_to_idx(). This
does away with the assumptions (1) mentioned above, and will work with
non continguous pstate ids. If no entry exists for a particular
pstate, then such a pstate is treated as being out of bounds. This
gets rid of assumption (2).

On all the existing platforms, where the pstates are 8-bit long
values, the new implementation of pstate_to_idx() takes constant time.

Signed-off-by: Gautham R. Shenoy 
---
 drivers/cpufreq/powernv-cpufreq.c | 85 +--
 1 file changed, 63 insertions(+), 22 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index f46b60f..8e3dbca 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -38,7 +39,8 @@
 #include 
 #include 
 
-#define POWERNV_MAX_PSTATES256
+#define POWERNV_MAX_PSTATES_ORDER  8
+#define POWERNV_MAX_PSTATES(1UL << (POWERNV_MAX_PSTATES_ORDER))
 #define PMSR_PSAFE_ENABLE  (1UL << 30)
 #define PMSR_SPR_EM_DISABLE(1UL << 31)
 #define MAX_PSTATE_SHIFT   32
@@ -92,6 +94,27 @@ struct global_pstate_info {
 };
 
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
+
+DEFINE_HASHTABLE(pstate_revmap, POWERNV_MAX_PSTATES_ORDER);
+/**
+ * struct pstate_idx_revmap_data: Entry in the hashmap pstate_revmap
+ *   indexed by a function of pstate id.
+ *
+ * @pstate_id: pstate id for this entry.
+ *
+ * @cpufreq_table_idx: Index into the powernv_freqs
+ *cpufreq_frequency_table for frequency
+ *corresponding to pstate_id.
+ *
+ * @hentry: hlist_node that hooks this entry into the pstate_revmap
+ * hashtable
+ */
+struct pstate_idx_revmap_data {
+   int pstate_id;
+   unsigned int cpufreq_table_idx;
+   struct hlist_node hentry;
+};
+
 u32 pstate_sign_prefix;
 static bool rebooting, throttled, occ_reset;
 
@@ -161,39 +184,47 @@ static inline int extract_pstate(u64 pmsr_val, unsigned 
int shift)
 #define extract_global_pstate(x) extract_pstate(x, GPSTATE_SHIFT)
 #define extract_max_pstate(x)  extract_pstate(x, MAX_PSTATE_SHIFT)
 
-/* Use following macros for conversions between pstate_id and index */
+/* Use following functions for conversions between pstate_id and index */
+
+/**
+ * idx_to_pstate : Returns the pstate id corresponding to the
+ *frequency in the cpufreq frequency table
+ *powernv_freqs indexed by @i.
+ *
+ *If @i is out of bound, this will return the pstate
+ *corresponding to the nominal frequency.
+ */
 static inline int idx_to_pstate(unsigned int i)
 {
if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
-   pr_warn_once("index %u is out of bound\n", i);
+   pr_warn_once("idx_to_pstate: index %u is out of bound\n", i);
return powernv_freqs[powernv_pstate_info.nominal].driver_data;
}
 
return powernv_freqs[i].driver_data;
 }
 
-static inline unsigned int pstate_to_idx(int pstate)
+/**
+ * pstate_to_idx : Returns the index in the cpufreq frequencytable
+ *powernv_freqs for the frequency whose corresponding
+ *pstate id is @pstate.
+ *
+ *If no frequency corresponding to @pstate is found,
+ *this will return the index of the nominal
+ *frequency.
+ */
+static unsigned int pstate_to_idx(int pstate)
 {
-   int min = powernv_freqs[powernv_pstate_info.min].driver_data;
-   int max = powernv_freqs[powernv_pstate_info.max].driver_data;
+   unsigned int key = pstate % POWERNV_MAX_PSTATES;
+   struct pstate_idx_revmap_data *revmap_data;
 
-   if (min > 0) {
-   if (unlikely((pstate < max) || (pstate > min))) {
-   pr_warn_once("pstate %d is out of bound\n", pstate);
-   return powernv_pstate_info.nominal;
-   }
-   } else {
-   if (unlikely((pstate > max) || (pstate < min))) {
-   pr_warn_once("pstate %d is out of 

[v3 PATCH 1/3] powernv-cpufreq: Add helper to extract pstate from PMSR

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

On POWERNV platform, the fields for pstates in the Power Management
Status Register (PMSR) and the Power Management Control Register
(PMCR) are 8-bits wide. On POWER8 the pstates are negatively numbered
while on POWER9 they are positively numbered.

The device-tree exports pstates as 32-bit entries. The device-tree
implementation sign-extends the 8-bit pstate values to obtain the
corresponding 32-bit entry.

Eg: On POWER8, a pstate value 0x82 [-126] is represented in the
device-tree as 0xfff82 while on POWER9, the same value 0x82 [130]
is represented in the device-tree as 0x0082.

The powernv-cpufreq driver implementation represents pstates using the
integer type. In multiple places in the driver, the code interprets
the pstates extracted from the PMSR as a signed byte and assigns it to
a integer variable to get the sign-extention.

On POWER9 platforms which have greater than 128 pstates, this results
in the driver performing incorrect sign-extention, and thereby
treating a legitimate pstate (say 130) as an invalid pstates (since it
is interpreted as -126).

This patch fixes the issue by implementing a helper function to
extract Pstates from PMSR register, and correctly sign-extend it to be
consistent with the values provided by the device-tree.

Signed-off-by: Gautham R. Shenoy 
---
 drivers/cpufreq/powernv-cpufreq.c | 37 +++--
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index b6d7c4c..f46b60f 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -41,11 +41,9 @@
 #define POWERNV_MAX_PSTATES256
 #define PMSR_PSAFE_ENABLE  (1UL << 30)
 #define PMSR_SPR_EM_DISABLE(1UL << 31)
-#define PMSR_MAX(x)((x >> 32) & 0xFF)
+#define MAX_PSTATE_SHIFT   32
 #define LPSTATE_SHIFT  48
 #define GPSTATE_SHIFT  56
-#define GET_LPSTATE(x) (((x) >> LPSTATE_SHIFT) & 0xFF)
-#define GET_GPSTATE(x) (((x) >> GPSTATE_SHIFT) & 0xFF)
 
 #define MAX_RAMP_DOWN_TIME 5120
 /*
@@ -94,6 +92,7 @@ struct global_pstate_info {
 };
 
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
+u32 pstate_sign_prefix;
 static bool rebooting, throttled, occ_reset;
 
 static const char * const throttle_reason[] = {
@@ -148,6 +147,20 @@ enum throttle_reason_type {
bool wof_enabled;
 } powernv_pstate_info;
 
+static inline int extract_pstate(u64 pmsr_val, unsigned int shift)
+{
+   int ret = ((pmsr_val >> shift) & 0xFF);
+
+   if (!ret)
+   return ret;
+
+   return (pstate_sign_prefix | ret);
+}
+
+#define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT)
+#define extract_global_pstate(x) extract_pstate(x, GPSTATE_SHIFT)
+#define extract_max_pstate(x)  extract_pstate(x, MAX_PSTATE_SHIFT)
+
 /* Use following macros for conversions between pstate_id and index */
 static inline int idx_to_pstate(unsigned int i)
 {
@@ -278,6 +291,9 @@ static int init_powernv_pstates(void)
 
powernv_pstate_info.nr_pstates = nr_pstates;
pr_debug("NR PStates %d\n", nr_pstates);
+
+   pstate_sign_prefix = pstate_min & ~0xFF;
+
for (i = 0; i < nr_pstates; i++) {
u32 id = be32_to_cpu(pstate_ids[i]);
u32 freq = be32_to_cpu(pstate_freqs[i]);
@@ -438,17 +454,10 @@ struct powernv_smp_call_data {
 static void powernv_read_cpu_freq(void *arg)
 {
unsigned long pmspr_val;
-   s8 local_pstate_id;
struct powernv_smp_call_data *freq_data = arg;
 
pmspr_val = get_pmspr(SPRN_PMSR);
-
-   /*
-* The local pstate id corresponds bits 48..55 in the PMSR.
-* Note: Watch out for the sign!
-*/
-   local_pstate_id = (pmspr_val >> 48) & 0xFF;
-   freq_data->pstate_id = local_pstate_id;
+   freq_data->pstate_id = extract_local_pstate(pmspr_val);
freq_data->freq = pstate_id_to_freq(freq_data->pstate_id);
 
pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n",
@@ -522,7 +531,7 @@ static void powernv_cpufreq_throttle_check(void *data)
chip = this_cpu_read(chip_info);
 
/* Check for Pmax Capping */
-   pmsr_pmax = (s8)PMSR_MAX(pmsr);
+   pmsr_pmax = extract_max_pstate(pmsr);
pmsr_pmax_idx = pstate_to_idx(pmsr_pmax);
if (pmsr_pmax_idx != powernv_pstate_info.max) {
if (chip->throttled)
@@ -645,8 +654,8 @@ void gpstate_timer_handler(struct timer_list *t)
 * value. Hence, read from PMCR to get correct data.
 */
val = get_pmspr(SPRN_PMCR);
-   freq_data.gpstate_id = (s8)GET_GPSTATE(val);
-   freq_data.pstate_id = (s8)GET_LPSTATE(val);
+   freq_data.gpstate_id = extract_global_pstate(val);
+   freq_data.pstate_id = extract_local_pstate(val);
if (freq_data.gpstate_id  == 

[v3 PATCH 2/3] powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

The code in powernv-cpufreq, makes the following two assumptions which
are not guaranteed by the device-tree bindings:

1) Pstate ids are continguous: This is used in pstate_to_idx() to
   obtain the reverse map from a pstate to it's corresponding
   entry into the cpufreq frequency table.

2) Every Pstate should always lie between the max and the min
   pstates that are explicitly reported in the device tree: This
   is used to determine whether a pstate reported by the PMSR is
   out of bounds.

Both these assumptions are unwarranted and can change on future
platforms.

In this patch, we maintain the reverse map from a pstate to it's index
in the cpufreq frequency table and use this in pstate_to_idx(). This
does away with the assumptions (1) mentioned above, and will work with
non continguous pstate ids. If no entry exists for a particular
pstate, then such a pstate is treated as being out of bounds. This
gets rid of assumption (2).

On all the existing platforms, where the pstates are 8-bit long
values, the new implementation of pstate_to_idx() takes constant time.

Signed-off-by: Gautham R. Shenoy 
---
 drivers/cpufreq/powernv-cpufreq.c | 85 +--
 1 file changed, 63 insertions(+), 22 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index f46b60f..8e3dbca 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -38,7 +39,8 @@
 #include 
 #include 
 
-#define POWERNV_MAX_PSTATES256
+#define POWERNV_MAX_PSTATES_ORDER  8
+#define POWERNV_MAX_PSTATES(1UL << (POWERNV_MAX_PSTATES_ORDER))
 #define PMSR_PSAFE_ENABLE  (1UL << 30)
 #define PMSR_SPR_EM_DISABLE(1UL << 31)
 #define MAX_PSTATE_SHIFT   32
@@ -92,6 +94,27 @@ struct global_pstate_info {
 };
 
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
+
+DEFINE_HASHTABLE(pstate_revmap, POWERNV_MAX_PSTATES_ORDER);
+/**
+ * struct pstate_idx_revmap_data: Entry in the hashmap pstate_revmap
+ *   indexed by a function of pstate id.
+ *
+ * @pstate_id: pstate id for this entry.
+ *
+ * @cpufreq_table_idx: Index into the powernv_freqs
+ *cpufreq_frequency_table for frequency
+ *corresponding to pstate_id.
+ *
+ * @hentry: hlist_node that hooks this entry into the pstate_revmap
+ * hashtable
+ */
+struct pstate_idx_revmap_data {
+   int pstate_id;
+   unsigned int cpufreq_table_idx;
+   struct hlist_node hentry;
+};
+
 u32 pstate_sign_prefix;
 static bool rebooting, throttled, occ_reset;
 
@@ -161,39 +184,47 @@ static inline int extract_pstate(u64 pmsr_val, unsigned 
int shift)
 #define extract_global_pstate(x) extract_pstate(x, GPSTATE_SHIFT)
 #define extract_max_pstate(x)  extract_pstate(x, MAX_PSTATE_SHIFT)
 
-/* Use following macros for conversions between pstate_id and index */
+/* Use following functions for conversions between pstate_id and index */
+
+/**
+ * idx_to_pstate : Returns the pstate id corresponding to the
+ *frequency in the cpufreq frequency table
+ *powernv_freqs indexed by @i.
+ *
+ *If @i is out of bound, this will return the pstate
+ *corresponding to the nominal frequency.
+ */
 static inline int idx_to_pstate(unsigned int i)
 {
if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
-   pr_warn_once("index %u is out of bound\n", i);
+   pr_warn_once("idx_to_pstate: index %u is out of bound\n", i);
return powernv_freqs[powernv_pstate_info.nominal].driver_data;
}
 
return powernv_freqs[i].driver_data;
 }
 
-static inline unsigned int pstate_to_idx(int pstate)
+/**
+ * pstate_to_idx : Returns the index in the cpufreq frequencytable
+ *powernv_freqs for the frequency whose corresponding
+ *pstate id is @pstate.
+ *
+ *If no frequency corresponding to @pstate is found,
+ *this will return the index of the nominal
+ *frequency.
+ */
+static unsigned int pstate_to_idx(int pstate)
 {
-   int min = powernv_freqs[powernv_pstate_info.min].driver_data;
-   int max = powernv_freqs[powernv_pstate_info.max].driver_data;
+   unsigned int key = pstate % POWERNV_MAX_PSTATES;
+   struct pstate_idx_revmap_data *revmap_data;
 
-   if (min > 0) {
-   if (unlikely((pstate < max) || (pstate > min))) {
-   pr_warn_once("pstate %d is out of bound\n", pstate);
-   return powernv_pstate_info.nominal;
-   }
-   } else {
-   if (unlikely((pstate > max) || (pstate < min))) {
-   pr_warn_once("pstate %d is out of bound\n", pstate);
-   return 

[v3 PATCH 1/3] powernv-cpufreq: Add helper to extract pstate from PMSR

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

On POWERNV platform, the fields for pstates in the Power Management
Status Register (PMSR) and the Power Management Control Register
(PMCR) are 8-bits wide. On POWER8 the pstates are negatively numbered
while on POWER9 they are positively numbered.

The device-tree exports pstates as 32-bit entries. The device-tree
implementation sign-extends the 8-bit pstate values to obtain the
corresponding 32-bit entry.

Eg: On POWER8, a pstate value 0x82 [-126] is represented in the
device-tree as 0xfff82 while on POWER9, the same value 0x82 [130]
is represented in the device-tree as 0x0082.

The powernv-cpufreq driver implementation represents pstates using the
integer type. In multiple places in the driver, the code interprets
the pstates extracted from the PMSR as a signed byte and assigns it to
a integer variable to get the sign-extention.

On POWER9 platforms which have greater than 128 pstates, this results
in the driver performing incorrect sign-extention, and thereby
treating a legitimate pstate (say 130) as an invalid pstates (since it
is interpreted as -126).

This patch fixes the issue by implementing a helper function to
extract Pstates from PMSR register, and correctly sign-extend it to be
consistent with the values provided by the device-tree.

Signed-off-by: Gautham R. Shenoy 
---
 drivers/cpufreq/powernv-cpufreq.c | 37 +++--
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index b6d7c4c..f46b60f 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -41,11 +41,9 @@
 #define POWERNV_MAX_PSTATES256
 #define PMSR_PSAFE_ENABLE  (1UL << 30)
 #define PMSR_SPR_EM_DISABLE(1UL << 31)
-#define PMSR_MAX(x)((x >> 32) & 0xFF)
+#define MAX_PSTATE_SHIFT   32
 #define LPSTATE_SHIFT  48
 #define GPSTATE_SHIFT  56
-#define GET_LPSTATE(x) (((x) >> LPSTATE_SHIFT) & 0xFF)
-#define GET_GPSTATE(x) (((x) >> GPSTATE_SHIFT) & 0xFF)
 
 #define MAX_RAMP_DOWN_TIME 5120
 /*
@@ -94,6 +92,7 @@ struct global_pstate_info {
 };
 
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
+u32 pstate_sign_prefix;
 static bool rebooting, throttled, occ_reset;
 
 static const char * const throttle_reason[] = {
@@ -148,6 +147,20 @@ enum throttle_reason_type {
bool wof_enabled;
 } powernv_pstate_info;
 
+static inline int extract_pstate(u64 pmsr_val, unsigned int shift)
+{
+   int ret = ((pmsr_val >> shift) & 0xFF);
+
+   if (!ret)
+   return ret;
+
+   return (pstate_sign_prefix | ret);
+}
+
+#define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT)
+#define extract_global_pstate(x) extract_pstate(x, GPSTATE_SHIFT)
+#define extract_max_pstate(x)  extract_pstate(x, MAX_PSTATE_SHIFT)
+
 /* Use following macros for conversions between pstate_id and index */
 static inline int idx_to_pstate(unsigned int i)
 {
@@ -278,6 +291,9 @@ static int init_powernv_pstates(void)
 
powernv_pstate_info.nr_pstates = nr_pstates;
pr_debug("NR PStates %d\n", nr_pstates);
+
+   pstate_sign_prefix = pstate_min & ~0xFF;
+
for (i = 0; i < nr_pstates; i++) {
u32 id = be32_to_cpu(pstate_ids[i]);
u32 freq = be32_to_cpu(pstate_freqs[i]);
@@ -438,17 +454,10 @@ struct powernv_smp_call_data {
 static void powernv_read_cpu_freq(void *arg)
 {
unsigned long pmspr_val;
-   s8 local_pstate_id;
struct powernv_smp_call_data *freq_data = arg;
 
pmspr_val = get_pmspr(SPRN_PMSR);
-
-   /*
-* The local pstate id corresponds bits 48..55 in the PMSR.
-* Note: Watch out for the sign!
-*/
-   local_pstate_id = (pmspr_val >> 48) & 0xFF;
-   freq_data->pstate_id = local_pstate_id;
+   freq_data->pstate_id = extract_local_pstate(pmspr_val);
freq_data->freq = pstate_id_to_freq(freq_data->pstate_id);
 
pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n",
@@ -522,7 +531,7 @@ static void powernv_cpufreq_throttle_check(void *data)
chip = this_cpu_read(chip_info);
 
/* Check for Pmax Capping */
-   pmsr_pmax = (s8)PMSR_MAX(pmsr);
+   pmsr_pmax = extract_max_pstate(pmsr);
pmsr_pmax_idx = pstate_to_idx(pmsr_pmax);
if (pmsr_pmax_idx != powernv_pstate_info.max) {
if (chip->throttled)
@@ -645,8 +654,8 @@ void gpstate_timer_handler(struct timer_list *t)
 * value. Hence, read from PMCR to get correct data.
 */
val = get_pmspr(SPRN_PMCR);
-   freq_data.gpstate_id = (s8)GET_GPSTATE(val);
-   freq_data.pstate_id = (s8)GET_LPSTATE(val);
+   freq_data.gpstate_id = extract_global_pstate(val);
+   freq_data.pstate_id = extract_local_pstate(val);
if (freq_data.gpstate_id  == freq_data.pstate_id) {

[v3 PATCH 3/3] powernv-cpufreq: Treat pstates as opaque 8-bit values

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

On POWER8 and POWER9, the PMSR and the PMCR registers define pstates
to be 8-bit wide values. The device-tree exports pstates as 32-bit
wide values of which the lower byte is the actual pstate.

The current implementation in the kernel treats pstates as integer
type, since it used to use the sign of the pstate for performing some
boundary-checks. This is no longer required after the patch
"powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous
pstates".

So, in this patch, we modify the powernv-cpufreq driver to uniformly
treat pstates as opaque 8-bit values obtained from the device-tree or
the PMCR. This simplifies the extract_pstate() helper function since
we no longer no longer require to worry about the sign-extentions.

Signed-off-by: Gautham R. Shenoy 
---
 drivers/cpufreq/powernv-cpufreq.c | 47 ---
 1 file changed, 19 insertions(+), 28 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index 8e3dbca..8a4e2ce 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -110,12 +110,11 @@ struct global_pstate_info {
  * hashtable
  */
 struct pstate_idx_revmap_data {
-   int pstate_id;
+   u8 pstate_id;
unsigned int cpufreq_table_idx;
struct hlist_node hentry;
 };
 
-u32 pstate_sign_prefix;
 static bool rebooting, throttled, occ_reset;
 
 static const char * const throttle_reason[] = {
@@ -170,14 +169,9 @@ enum throttle_reason_type {
bool wof_enabled;
 } powernv_pstate_info;
 
-static inline int extract_pstate(u64 pmsr_val, unsigned int shift)
+static inline u8 extract_pstate(u64 pmsr_val, unsigned int shift)
 {
-   int ret = ((pmsr_val >> shift) & 0xFF);
-
-   if (!ret)
-   return ret;
-
-   return (pstate_sign_prefix | ret);
+   return ((pmsr_val >> shift) & 0xFF);
 }
 
 #define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT)
@@ -194,7 +188,7 @@ static inline int extract_pstate(u64 pmsr_val, unsigned int 
shift)
  *If @i is out of bound, this will return the pstate
  *corresponding to the nominal frequency.
  */
-static inline int idx_to_pstate(unsigned int i)
+static inline u8 idx_to_pstate(unsigned int i)
 {
if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
pr_warn_once("idx_to_pstate: index %u is out of bound\n", i);
@@ -213,7 +207,7 @@ static inline int idx_to_pstate(unsigned int i)
  *this will return the index of the nominal
  *frequency.
  */
-static unsigned int pstate_to_idx(int pstate)
+static unsigned int pstate_to_idx(u8 pstate)
 {
unsigned int key = pstate % POWERNV_MAX_PSTATES;
struct pstate_idx_revmap_data *revmap_data;
@@ -223,7 +217,7 @@ static unsigned int pstate_to_idx(int pstate)
return revmap_data->cpufreq_table_idx;
}
 
-   pr_warn_once("pstate_to_idx: pstate %d not found\n", pstate);
+   pr_warn_once("pstate_to_idx: pstate 0x%x not found\n", pstate);
return powernv_pstate_info.nominal;
 }
 
@@ -291,7 +285,7 @@ static int init_powernv_pstates(void)
powernv_pstate_info.wof_enabled = true;
 
 next:
-   pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min,
+   pr_info("cpufreq pstate min 0x%x nominal 0x%x max 0x%x\n", pstate_min,
pstate_nominal, pstate_max);
pr_info("Workload Optimized Frequency is %s in the platform\n",
(powernv_pstate_info.wof_enabled) ? "enabled" : "disabled");
@@ -323,8 +317,6 @@ static int init_powernv_pstates(void)
powernv_pstate_info.nr_pstates = nr_pstates;
pr_debug("NR PStates %d\n", nr_pstates);
 
-   pstate_sign_prefix = pstate_min & ~0xFF;
-
for (i = 0; i < nr_pstates; i++) {
u32 id = be32_to_cpu(pstate_ids[i]);
u32 freq = be32_to_cpu(pstate_freqs[i]);
@@ -333,14 +325,14 @@ static int init_powernv_pstates(void)
 
pr_debug("PState id %d freq %d MHz\n", id, freq);
powernv_freqs[i].frequency = freq * 1000; /* kHz */
-   powernv_freqs[i].driver_data = id;
+   powernv_freqs[i].driver_data = id & 0xFF;
 
revmap_data = (struct pstate_idx_revmap_data *)
  kmalloc(sizeof(*revmap_data), GFP_KERNEL);
 
-   revmap_data->pstate_id = id;
+   revmap_data->pstate_id = id & 0xFF;
revmap_data->cpufreq_table_idx = i;
-   key = id % POWERNV_MAX_PSTATES;
+   key = (revmap_data->pstate_id) % POWERNV_MAX_PSTATES;
hash_add(pstate_revmap, _data->hentry, key);
 
if (id == pstate_max)
@@ -364,14 +356,13 @@ static int init_powernv_pstates(void)
 }
 
 /* Returns the CPU frequency corresponding to the pstate_id. */
-static unsigned 

[v3 PATCH 3/3] powernv-cpufreq: Treat pstates as opaque 8-bit values

2017-12-12 Thread Gautham R. Shenoy
From: "Gautham R. Shenoy" 

On POWER8 and POWER9, the PMSR and the PMCR registers define pstates
to be 8-bit wide values. The device-tree exports pstates as 32-bit
wide values of which the lower byte is the actual pstate.

The current implementation in the kernel treats pstates as integer
type, since it used to use the sign of the pstate for performing some
boundary-checks. This is no longer required after the patch
"powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous
pstates".

So, in this patch, we modify the powernv-cpufreq driver to uniformly
treat pstates as opaque 8-bit values obtained from the device-tree or
the PMCR. This simplifies the extract_pstate() helper function since
we no longer no longer require to worry about the sign-extentions.

Signed-off-by: Gautham R. Shenoy 
---
 drivers/cpufreq/powernv-cpufreq.c | 47 ---
 1 file changed, 19 insertions(+), 28 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index 8e3dbca..8a4e2ce 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -110,12 +110,11 @@ struct global_pstate_info {
  * hashtable
  */
 struct pstate_idx_revmap_data {
-   int pstate_id;
+   u8 pstate_id;
unsigned int cpufreq_table_idx;
struct hlist_node hentry;
 };
 
-u32 pstate_sign_prefix;
 static bool rebooting, throttled, occ_reset;
 
 static const char * const throttle_reason[] = {
@@ -170,14 +169,9 @@ enum throttle_reason_type {
bool wof_enabled;
 } powernv_pstate_info;
 
-static inline int extract_pstate(u64 pmsr_val, unsigned int shift)
+static inline u8 extract_pstate(u64 pmsr_val, unsigned int shift)
 {
-   int ret = ((pmsr_val >> shift) & 0xFF);
-
-   if (!ret)
-   return ret;
-
-   return (pstate_sign_prefix | ret);
+   return ((pmsr_val >> shift) & 0xFF);
 }
 
 #define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT)
@@ -194,7 +188,7 @@ static inline int extract_pstate(u64 pmsr_val, unsigned int 
shift)
  *If @i is out of bound, this will return the pstate
  *corresponding to the nominal frequency.
  */
-static inline int idx_to_pstate(unsigned int i)
+static inline u8 idx_to_pstate(unsigned int i)
 {
if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
pr_warn_once("idx_to_pstate: index %u is out of bound\n", i);
@@ -213,7 +207,7 @@ static inline int idx_to_pstate(unsigned int i)
  *this will return the index of the nominal
  *frequency.
  */
-static unsigned int pstate_to_idx(int pstate)
+static unsigned int pstate_to_idx(u8 pstate)
 {
unsigned int key = pstate % POWERNV_MAX_PSTATES;
struct pstate_idx_revmap_data *revmap_data;
@@ -223,7 +217,7 @@ static unsigned int pstate_to_idx(int pstate)
return revmap_data->cpufreq_table_idx;
}
 
-   pr_warn_once("pstate_to_idx: pstate %d not found\n", pstate);
+   pr_warn_once("pstate_to_idx: pstate 0x%x not found\n", pstate);
return powernv_pstate_info.nominal;
 }
 
@@ -291,7 +285,7 @@ static int init_powernv_pstates(void)
powernv_pstate_info.wof_enabled = true;
 
 next:
-   pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min,
+   pr_info("cpufreq pstate min 0x%x nominal 0x%x max 0x%x\n", pstate_min,
pstate_nominal, pstate_max);
pr_info("Workload Optimized Frequency is %s in the platform\n",
(powernv_pstate_info.wof_enabled) ? "enabled" : "disabled");
@@ -323,8 +317,6 @@ static int init_powernv_pstates(void)
powernv_pstate_info.nr_pstates = nr_pstates;
pr_debug("NR PStates %d\n", nr_pstates);
 
-   pstate_sign_prefix = pstate_min & ~0xFF;
-
for (i = 0; i < nr_pstates; i++) {
u32 id = be32_to_cpu(pstate_ids[i]);
u32 freq = be32_to_cpu(pstate_freqs[i]);
@@ -333,14 +325,14 @@ static int init_powernv_pstates(void)
 
pr_debug("PState id %d freq %d MHz\n", id, freq);
powernv_freqs[i].frequency = freq * 1000; /* kHz */
-   powernv_freqs[i].driver_data = id;
+   powernv_freqs[i].driver_data = id & 0xFF;
 
revmap_data = (struct pstate_idx_revmap_data *)
  kmalloc(sizeof(*revmap_data), GFP_KERNEL);
 
-   revmap_data->pstate_id = id;
+   revmap_data->pstate_id = id & 0xFF;
revmap_data->cpufreq_table_idx = i;
-   key = id % POWERNV_MAX_PSTATES;
+   key = (revmap_data->pstate_id) % POWERNV_MAX_PSTATES;
hash_add(pstate_revmap, _data->hentry, key);
 
if (id == pstate_max)
@@ -364,14 +356,13 @@ static int init_powernv_pstates(void)
 }
 
 /* Returns the CPU frequency corresponding to the pstate_id. */
-static unsigned int pstate_id_to_freq(int pstate_id)
+static 

Re: [RFC PATCH 5/9] ethtool: implement GET_DRVINFO message

2017-12-12 Thread Jiri Pirko
Wed, Dec 13, 2017 at 12:54:39AM CET, mkube...@suse.cz wrote:
>On Mon, Dec 11, 2017 at 05:16:01PM +0100, Jiri Pirko wrote:
>> Mon, Dec 11, 2017 at 02:54:01PM CET, mkube...@suse.cz wrote:
>> >+
>> >+ETHA_DRVINFO_DRIVER(string)driver name
>> >+ETHA_DRVINFO_VERSION   (string)driver version
>> 
>> You use 3 prefixes:
>> ETHTOOL_ for cmd
>> ETHA_ for attrs
>> ethnl_ for function
>> 
>> I suggest to sync this, perhaps to:
>> ETHNL_CMD_*
>> ETHNL_ATTR_*
>> ethnl_*
>> ?
>
>Switching to ETHNL_CMD_* is certainly a good idea. For attributes, I'm a
>bit worried that ETHNL_ATTR_ prefix might make it even harder to fit
>into the 80 characters per line limit. I'll try and see what it would
>look like.
>
>> >+ETHA_DRVINFO_FWVERSION (string)firmware version
>> >+ETHA_DRVINFO_BUSINFO   (string)device bus address
>> >+ETHA_DRVINFO_EROM_VER  (string)expansion ROM version
>> >+ETHA_DRVINFO_N_PRIV_FLAGS  (u32)   number of private flags
>> >+ETHA_DRVINFO_N_STATS   (u32)   number of device stats
>> >+ETHA_DRVINFO_TESTINFO_LEN  (u32)   number of test results
>> >+ETHA_DRVINFO_EEDUMP_LEN(u32)   EEPROM dump size
>> >+ETHA_DRVINFO_REGDUMP_LEN   (u32)   register dump size
>> 
>> We are now working on providing various fw memory regions dump in
>> devlink. It makes sense to have it in devlink for couple of reasons:
>> 1) per-asic, not netdev specific, therefore does not really make sense
>>to have netdev as handle, but rather devlink handle.
>> 2) snapshot support - we need to provide support for getting snapshot
>>(for example on failure), transferring to user and deleting it
>>(remove from driver memory).
>> 
>> Also, driver name, version, fwversion, etc is per-asic. Would make sense
>> to have it in devlink as well.
>> 
>> I think this is great opprotunity to move things where they should be to
>> be alligned with the current world and kernel infrastructure.
>
>IMHO this depends on the question whether we are going to rework also
>the interface between kernel and NIC drivers (currently ethtool_ops).
>If we are, it would make good sense to split the information in both
>interfaces. If not, it doesn't seem to make userspace do two queries,
>each getting one part of the same information provided by NIC.

Yeah, agreed. I believe we should.


>
>Also, I must admit that one thing I dislike about the iw tool is that it
>pushes me to distinguish between operations on "phy" and "dev". While
>I understand that it makes perfect sense for someone familiar with the
>internals, it's quite annoying for an occasional "consumer". It would be
>sad if we created a set of perfectly logical and clean tools and
>(almost) 20 years later, people still used old ioctl based ethtool
>because "it's what they are used to and it works just fine for them"
>(like they do with ifconfig, netstat or brctl).

Good documentation should take care of that.



>
>Michal


Re: [RFC PATCH 5/9] ethtool: implement GET_DRVINFO message

2017-12-12 Thread Jiri Pirko
Wed, Dec 13, 2017 at 12:54:39AM CET, mkube...@suse.cz wrote:
>On Mon, Dec 11, 2017 at 05:16:01PM +0100, Jiri Pirko wrote:
>> Mon, Dec 11, 2017 at 02:54:01PM CET, mkube...@suse.cz wrote:
>> >+
>> >+ETHA_DRVINFO_DRIVER(string)driver name
>> >+ETHA_DRVINFO_VERSION   (string)driver version
>> 
>> You use 3 prefixes:
>> ETHTOOL_ for cmd
>> ETHA_ for attrs
>> ethnl_ for function
>> 
>> I suggest to sync this, perhaps to:
>> ETHNL_CMD_*
>> ETHNL_ATTR_*
>> ethnl_*
>> ?
>
>Switching to ETHNL_CMD_* is certainly a good idea. For attributes, I'm a
>bit worried that ETHNL_ATTR_ prefix might make it even harder to fit
>into the 80 characters per line limit. I'll try and see what it would
>look like.
>
>> >+ETHA_DRVINFO_FWVERSION (string)firmware version
>> >+ETHA_DRVINFO_BUSINFO   (string)device bus address
>> >+ETHA_DRVINFO_EROM_VER  (string)expansion ROM version
>> >+ETHA_DRVINFO_N_PRIV_FLAGS  (u32)   number of private flags
>> >+ETHA_DRVINFO_N_STATS   (u32)   number of device stats
>> >+ETHA_DRVINFO_TESTINFO_LEN  (u32)   number of test results
>> >+ETHA_DRVINFO_EEDUMP_LEN(u32)   EEPROM dump size
>> >+ETHA_DRVINFO_REGDUMP_LEN   (u32)   register dump size
>> 
>> We are now working on providing various fw memory regions dump in
>> devlink. It makes sense to have it in devlink for couple of reasons:
>> 1) per-asic, not netdev specific, therefore does not really make sense
>>to have netdev as handle, but rather devlink handle.
>> 2) snapshot support - we need to provide support for getting snapshot
>>(for example on failure), transferring to user and deleting it
>>(remove from driver memory).
>> 
>> Also, driver name, version, fwversion, etc is per-asic. Would make sense
>> to have it in devlink as well.
>> 
>> I think this is great opprotunity to move things where they should be to
>> be alligned with the current world and kernel infrastructure.
>
>IMHO this depends on the question whether we are going to rework also
>the interface between kernel and NIC drivers (currently ethtool_ops).
>If we are, it would make good sense to split the information in both
>interfaces. If not, it doesn't seem to make userspace do two queries,
>each getting one part of the same information provided by NIC.

Yeah, agreed. I believe we should.


>
>Also, I must admit that one thing I dislike about the iw tool is that it
>pushes me to distinguish between operations on "phy" and "dev". While
>I understand that it makes perfect sense for someone familiar with the
>internals, it's quite annoying for an occasional "consumer". It would be
>sad if we created a set of perfectly logical and clean tools and
>(almost) 20 years later, people still used old ioctl based ethtool
>because "it's what they are used to and it works just fine for them"
>(like they do with ifconfig, netstat or brctl).

Good documentation should take care of that.



>
>Michal


Re: [PATCH] vfio: Simplify capability helper

2017-12-12 Thread Peter Xu
On Tue, Dec 12, 2017 at 12:59:39PM -0700, Alex Williamson wrote:
> The vfio_info_add_capability() helper requires the caller to pass a
> capability ID, which it then uses to fill in header fields, assuming
> hard coded versions.  This makes for an awkward and rigid interface.
> The only thing we want this helper to do is allocate sufficient
> space in the caps buffer and chain this capability into the list.
> Reduce it to that simple task.
> 
> Signed-off-by: Alex Williamson 

Reviewed-by: Peter Xu 

Though during review I had a question related to the function
msix_sparse_mmap_cap(): Is it possible that one PCI device BAR is very
small (e.g., 4K) that only contains the MSI-X table (and another small
PBA area)?  If so, should we just mark that region unmappable instead
of setting vfio_region_info_cap_sparse_mmap.nr_areas to 1 in
msix_sparse_mmap_cap()?

/* If MSI-X table is aligned to the start or end, only one area */
if (((vdev->msix_offset & PAGE_MASK) == 0) ||
(PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) >= end))
nr_areas = 1;

Thanks,

-- 
Peter Xu


Re: [PATCH] vfio: Simplify capability helper

2017-12-12 Thread Peter Xu
On Tue, Dec 12, 2017 at 12:59:39PM -0700, Alex Williamson wrote:
> The vfio_info_add_capability() helper requires the caller to pass a
> capability ID, which it then uses to fill in header fields, assuming
> hard coded versions.  This makes for an awkward and rigid interface.
> The only thing we want this helper to do is allocate sufficient
> space in the caps buffer and chain this capability into the list.
> Reduce it to that simple task.
> 
> Signed-off-by: Alex Williamson 

Reviewed-by: Peter Xu 

Though during review I had a question related to the function
msix_sparse_mmap_cap(): Is it possible that one PCI device BAR is very
small (e.g., 4K) that only contains the MSI-X table (and another small
PBA area)?  If so, should we just mark that region unmappable instead
of setting vfio_region_info_cap_sparse_mmap.nr_areas to 1 in
msix_sparse_mmap_cap()?

/* If MSI-X table is aligned to the start or end, only one area */
if (((vdev->msix_offset & PAGE_MASK) == 0) ||
(PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) >= end))
nr_areas = 1;

Thanks,

-- 
Peter Xu


Re: [PATCH 4.14 000/164] 4.14.6-stable review

2017-12-12 Thread Marek Szyprowski

Hi Shuah and Greg,

On 2017-12-12 15:47, Shuah Khan wrote:

On 12/12/2017 05:43 AM, Greg Kroah-Hartman wrote:

This is the start of the stable review cycle for the 4.14.6 release.
There are 164 patches in this series, all will be posted as a response
to this one.  If anyone has any issues with these being applied, please
let me know.

Responses should be made by Thu Dec 14 12:34:08 UTC 2017.
Anything received after that time might be too late.

The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.6-rc1.gz
or in the git tree and branch at:
   git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
linux-4.14.y
and the diffstat can be found below.

thanks,

greg k-h

  

Daniel Vetter 
 drm: safely free connectors from connector_iter

Marek Szyprowski 
 drm/bridge: analogix dp: Fix runtime PM state in get_modes() callback


The above two patches have been found to be the cause of boot hang on
exynos Peach Pi(t) chromebooks.

I am adding Daniel and Marek to the thread.


The deadlock is caused by the Daniels patch. My patch only changes the order
of device initialization what might hide or reveal bug related to 
Daniels patch.


My drm/bridge patch it is definitely needed for v4.14 stable to fix boot 
issue

on Samsung Snow Chromebooks (Exynos 5250 based).

Best regards

--
Marek Szyprowski, PhD
Samsung R Institute Poland



Re: [PATCH 4.14 000/164] 4.14.6-stable review

2017-12-12 Thread Marek Szyprowski

Hi Shuah and Greg,

On 2017-12-12 15:47, Shuah Khan wrote:

On 12/12/2017 05:43 AM, Greg Kroah-Hartman wrote:

This is the start of the stable review cycle for the 4.14.6 release.
There are 164 patches in this series, all will be posted as a response
to this one.  If anyone has any issues with these being applied, please
let me know.

Responses should be made by Thu Dec 14 12:34:08 UTC 2017.
Anything received after that time might be too late.

The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.6-rc1.gz
or in the git tree and branch at:
   git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
linux-4.14.y
and the diffstat can be found below.

thanks,

greg k-h

  

Daniel Vetter 
 drm: safely free connectors from connector_iter

Marek Szyprowski 
 drm/bridge: analogix dp: Fix runtime PM state in get_modes() callback


The above two patches have been found to be the cause of boot hang on
exynos Peach Pi(t) chromebooks.

I am adding Daniel and Marek to the thread.


The deadlock is caused by the Daniels patch. My patch only changes the order
of device initialization what might hide or reveal bug related to 
Daniels patch.


My drm/bridge patch it is definitely needed for v4.14 stable to fix boot 
issue

on Samsung Snow Chromebooks (Exynos 5250 based).

Best regards

--
Marek Szyprowski, PhD
Samsung R Institute Poland



[PATCH v2 01/11] ASoC: fsl_ssi: Rename fsl_ssi_private to fsl_ssi

2017-12-12 Thread Nicolin Chen
Shorten the private data structure to save some wrapped lines.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 456 +++-
 1 file changed, 220 insertions(+), 236 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c350117..84d2f7e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -185,7 +185,7 @@ struct fsl_ssi_soc_data {
 };
 
 /**
- * fsl_ssi_private: per-SSI private data
+ * fsl_ssi: per-SSI private data
  *
  * @reg: Pointer to the regmap registers
  * @irq: IRQ of this SSI
@@ -224,7 +224,7 @@ struct fsl_ssi_soc_data {
  * @dma_maxburst: max number of words to transfer in one go.  So far,
  * this is always the same as fifo_watermark.
  */
-struct fsl_ssi_private {
+struct fsl_ssi {
struct regmap *regs;
int irq;
struct snd_soc_dai_driver cpu_dai_drv;
@@ -325,21 +325,21 @@ static const struct of_device_id fsl_ssi_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
 
-static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private)
+static bool fsl_ssi_is_ac97(struct fsl_ssi *ssi)
 {
-   return (ssi_private->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
+   return (ssi->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
SND_SOC_DAIFMT_AC97;
 }
 
-static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private)
+static bool fsl_ssi_is_i2s_master(struct fsl_ssi *ssi)
 {
-   return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
+   return (ssi->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBS_CFS;
 }
 
-static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private *ssi_private)
+static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi *ssi)
 {
-   return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
+   return (ssi->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBM_CFS;
 }
 /**
@@ -352,12 +352,12 @@ static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private 
*ssi_private)
  * This interrupt handler is used only to gather statistics.
  *
  * @irq: IRQ of the SSI device
- * @dev_id: pointer to the ssi_private structure for this SSI device
+ * @dev_id: pointer to the fsl_ssi structure for this SSI device
  */
 static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 {
-   struct fsl_ssi_private *ssi_private = dev_id;
-   struct regmap *regs = ssi_private->regs;
+   struct fsl_ssi *ssi = dev_id;
+   struct regmap *regs = ssi->regs;
__be32 sisr;
__be32 sisr2;
 
@@ -367,12 +367,12 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 */
regmap_read(regs, CCSR_SSI_SISR, );
 
-   sisr2 = sisr & ssi_private->soc->sisr_write_mask;
+   sisr2 = sisr & ssi->soc->sisr_write_mask;
/* Clear the bits that we set */
if (sisr2)
regmap_write(regs, CCSR_SSI_SISR, sisr2);
 
-   fsl_ssi_dbg_isr(_private->dbg_stats, sisr);
+   fsl_ssi_dbg_isr(>dbg_stats, sisr);
 
return IRQ_HANDLED;
 }
@@ -380,11 +380,10 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 /*
  * Enable/Disable all rx/tx config flags at once.
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
-   bool enable)
+static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
 {
-   struct regmap *regs = ssi_private->regs;
-   struct fsl_ssi_rxtx_reg_val *vals = _private->rxtx_reg_val;
+   struct regmap *regs = ssi->regs;
+   struct fsl_ssi_rxtx_reg_val *vals = >rxtx_reg_val;
 
if (enable) {
regmap_update_bits(regs, CCSR_SSI_SIER,
@@ -414,14 +413,13 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi_private 
*ssi_private,
  * Note: The SOR is not documented in recent IMX datasheet, but
  * is described in IMX51 reference manual at section 56.3.3.15.
  */
-static void fsl_ssi_fifo_clear(struct fsl_ssi_private *ssi_private,
-   bool is_rx)
+static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
 {
if (is_rx) {
-   regmap_update_bits(ssi_private->regs, CCSR_SSI_SOR,
+   regmap_update_bits(ssi->regs, CCSR_SSI_SOR,
CCSR_SSI_SOR_RX_CLR, CCSR_SSI_SOR_RX_CLR);
} else {
-   regmap_update_bits(ssi_private->regs, CCSR_SSI_SOR,
+   regmap_update_bits(ssi->regs, CCSR_SSI_SOR,
CCSR_SSI_SOR_TX_CLR, CCSR_SSI_SOR_TX_CLR);
}
 }
@@ -448,12 +446,12 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi_private 
*ssi_private,
 
 /*
  * Enable/Disable a ssi configuration. You have to pass either
- * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
+ * ssi->rxtx_reg_val.rx or tx as vals parameter.
  */
-static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
+static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
struct fsl_ssi_reg_val *vals)
 {
-   struct regmap *regs 

[PATCH v2 01/11] ASoC: fsl_ssi: Rename fsl_ssi_private to fsl_ssi

2017-12-12 Thread Nicolin Chen
Shorten the private data structure to save some wrapped lines.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 456 +++-
 1 file changed, 220 insertions(+), 236 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c350117..84d2f7e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -185,7 +185,7 @@ struct fsl_ssi_soc_data {
 };
 
 /**
- * fsl_ssi_private: per-SSI private data
+ * fsl_ssi: per-SSI private data
  *
  * @reg: Pointer to the regmap registers
  * @irq: IRQ of this SSI
@@ -224,7 +224,7 @@ struct fsl_ssi_soc_data {
  * @dma_maxburst: max number of words to transfer in one go.  So far,
  * this is always the same as fifo_watermark.
  */
-struct fsl_ssi_private {
+struct fsl_ssi {
struct regmap *regs;
int irq;
struct snd_soc_dai_driver cpu_dai_drv;
@@ -325,21 +325,21 @@ static const struct of_device_id fsl_ssi_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
 
-static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private)
+static bool fsl_ssi_is_ac97(struct fsl_ssi *ssi)
 {
-   return (ssi_private->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
+   return (ssi->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
SND_SOC_DAIFMT_AC97;
 }
 
-static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private)
+static bool fsl_ssi_is_i2s_master(struct fsl_ssi *ssi)
 {
-   return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
+   return (ssi->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBS_CFS;
 }
 
-static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private *ssi_private)
+static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi *ssi)
 {
-   return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
+   return (ssi->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) ==
SND_SOC_DAIFMT_CBM_CFS;
 }
 /**
@@ -352,12 +352,12 @@ static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private 
*ssi_private)
  * This interrupt handler is used only to gather statistics.
  *
  * @irq: IRQ of the SSI device
- * @dev_id: pointer to the ssi_private structure for this SSI device
+ * @dev_id: pointer to the fsl_ssi structure for this SSI device
  */
 static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 {
-   struct fsl_ssi_private *ssi_private = dev_id;
-   struct regmap *regs = ssi_private->regs;
+   struct fsl_ssi *ssi = dev_id;
+   struct regmap *regs = ssi->regs;
__be32 sisr;
__be32 sisr2;
 
@@ -367,12 +367,12 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 */
regmap_read(regs, CCSR_SSI_SISR, );
 
-   sisr2 = sisr & ssi_private->soc->sisr_write_mask;
+   sisr2 = sisr & ssi->soc->sisr_write_mask;
/* Clear the bits that we set */
if (sisr2)
regmap_write(regs, CCSR_SSI_SISR, sisr2);
 
-   fsl_ssi_dbg_isr(_private->dbg_stats, sisr);
+   fsl_ssi_dbg_isr(>dbg_stats, sisr);
 
return IRQ_HANDLED;
 }
@@ -380,11 +380,10 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 /*
  * Enable/Disable all rx/tx config flags at once.
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
-   bool enable)
+static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
 {
-   struct regmap *regs = ssi_private->regs;
-   struct fsl_ssi_rxtx_reg_val *vals = _private->rxtx_reg_val;
+   struct regmap *regs = ssi->regs;
+   struct fsl_ssi_rxtx_reg_val *vals = >rxtx_reg_val;
 
if (enable) {
regmap_update_bits(regs, CCSR_SSI_SIER,
@@ -414,14 +413,13 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi_private 
*ssi_private,
  * Note: The SOR is not documented in recent IMX datasheet, but
  * is described in IMX51 reference manual at section 56.3.3.15.
  */
-static void fsl_ssi_fifo_clear(struct fsl_ssi_private *ssi_private,
-   bool is_rx)
+static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
 {
if (is_rx) {
-   regmap_update_bits(ssi_private->regs, CCSR_SSI_SOR,
+   regmap_update_bits(ssi->regs, CCSR_SSI_SOR,
CCSR_SSI_SOR_RX_CLR, CCSR_SSI_SOR_RX_CLR);
} else {
-   regmap_update_bits(ssi_private->regs, CCSR_SSI_SOR,
+   regmap_update_bits(ssi->regs, CCSR_SSI_SOR,
CCSR_SSI_SOR_TX_CLR, CCSR_SSI_SOR_TX_CLR);
}
 }
@@ -448,12 +446,12 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi_private 
*ssi_private,
 
 /*
  * Enable/Disable a ssi configuration. You have to pass either
- * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
+ * ssi->rxtx_reg_val.rx or tx as vals parameter.
  */
-static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
+static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
struct fsl_ssi_reg_val *vals)
 {
-   struct regmap *regs = ssi_private->regs;
+   

[PATCH v2 06/11] ASoC: fsl_ssi: Refine printk outputs

2017-12-12 Thread Nicolin Chen
This patches unifies the error message in the "failed to " format.

It also reduces the length of one line and adds spaces to an operator.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 9a3db08..d3bb662 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -701,7 +701,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
 * never greater than 1/5 IPG clock rate
 */
if (freq * 5 > clk_get_rate(ssi->clk)) {
-   dev_err(cpu_dai->dev, "bitclk > ipgclk/5\n");
+   dev_err(cpu_dai->dev, "bitclk > ipgclk / 5\n");
return -EINVAL;
}
 
@@ -868,7 +868,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
ssi->dai_fmt = fmt;
 
if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "baudclk is missing which is necessary for master 
mode\n");
+   dev_err(dev, "missing baudclk for master mode\n");
return -EINVAL;
}
 
@@ -1284,7 +1284,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
ssi->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ssi->clk)) {
ret = PTR_ERR(ssi->clk);
-   dev_err(dev, "could not get clock: %d\n", ret);
+   dev_err(dev, "failed to get clock: %d\n", ret);
return ret;
}
 
@@ -1300,7 +1300,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
/* Do not error out for slave cases that live without a baud clock */
ssi->baudclk = devm_clk_get(dev, "baud");
if (IS_ERR(ssi->baudclk))
-   dev_dbg(dev, "could not get baud clock: %ld\n",
+   dev_dbg(dev, "failed to get baud clock: %ld\n",
 PTR_ERR(ssi->baudclk));
 
ssi->dma_params_tx.maxburst = ssi->dma_maxburst;
@@ -1421,7 +1421,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
  );
}
if (IS_ERR(ssi->regs)) {
-   dev_err(dev, "Failed to init register map\n");
+   dev_err(dev, "failed to init register map\n");
return PTR_ERR(ssi->regs);
}
 
@@ -1480,7 +1480,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
mutex_init(>ac97_reg_lock);
ret = snd_soc_set_ac97_ops_of_reset(_ssi_ac97_ops, pdev);
if (ret) {
-   dev_err(dev, "could not set AC'97 ops\n");
+   dev_err(dev, "failed to set AC'97 ops\n");
goto error_ac97_ops;
}
}
@@ -1496,7 +1496,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, ssi->irq, fsl_ssi_isr, 0,
   dev_name(dev), ssi);
if (ret < 0) {
-   dev_err(dev, "could not claim irq %u\n", ssi->irq);
+   dev_err(dev, "failed to claim irq %u\n", ssi->irq);
goto error_asoc_register;
}
}
@@ -1538,7 +1538,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
ret = of_property_read_u32(np, "cell-index", _idx);
if (ret) {
-   dev_err(dev, "cannot get SSI index property\n");
+   dev_err(dev, "failed to get SSI index property\n");
goto error_sound_card;
}
 
-- 
2.7.4



[PATCH v2 06/11] ASoC: fsl_ssi: Refine printk outputs

2017-12-12 Thread Nicolin Chen
This patches unifies the error message in the "failed to " format.

It also reduces the length of one line and adds spaces to an operator.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 9a3db08..d3bb662 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -701,7 +701,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
 * never greater than 1/5 IPG clock rate
 */
if (freq * 5 > clk_get_rate(ssi->clk)) {
-   dev_err(cpu_dai->dev, "bitclk > ipgclk/5\n");
+   dev_err(cpu_dai->dev, "bitclk > ipgclk / 5\n");
return -EINVAL;
}
 
@@ -868,7 +868,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
ssi->dai_fmt = fmt;
 
if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "baudclk is missing which is necessary for master 
mode\n");
+   dev_err(dev, "missing baudclk for master mode\n");
return -EINVAL;
}
 
@@ -1284,7 +1284,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
ssi->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ssi->clk)) {
ret = PTR_ERR(ssi->clk);
-   dev_err(dev, "could not get clock: %d\n", ret);
+   dev_err(dev, "failed to get clock: %d\n", ret);
return ret;
}
 
@@ -1300,7 +1300,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
/* Do not error out for slave cases that live without a baud clock */
ssi->baudclk = devm_clk_get(dev, "baud");
if (IS_ERR(ssi->baudclk))
-   dev_dbg(dev, "could not get baud clock: %ld\n",
+   dev_dbg(dev, "failed to get baud clock: %ld\n",
 PTR_ERR(ssi->baudclk));
 
ssi->dma_params_tx.maxburst = ssi->dma_maxburst;
@@ -1421,7 +1421,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
  );
}
if (IS_ERR(ssi->regs)) {
-   dev_err(dev, "Failed to init register map\n");
+   dev_err(dev, "failed to init register map\n");
return PTR_ERR(ssi->regs);
}
 
@@ -1480,7 +1480,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
mutex_init(>ac97_reg_lock);
ret = snd_soc_set_ac97_ops_of_reset(_ssi_ac97_ops, pdev);
if (ret) {
-   dev_err(dev, "could not set AC'97 ops\n");
+   dev_err(dev, "failed to set AC'97 ops\n");
goto error_ac97_ops;
}
}
@@ -1496,7 +1496,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, ssi->irq, fsl_ssi_isr, 0,
   dev_name(dev), ssi);
if (ret < 0) {
-   dev_err(dev, "could not claim irq %u\n", ssi->irq);
+   dev_err(dev, "failed to claim irq %u\n", ssi->irq);
goto error_asoc_register;
}
}
@@ -1538,7 +1538,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
ret = of_property_read_u32(np, "cell-index", _idx);
if (ret) {
-   dev_err(dev, "cannot get SSI index property\n");
+   dev_err(dev, "failed to get SSI index property\n");
goto error_sound_card;
}
 
-- 
2.7.4



[PATCH v2 07/11] ASoC: fsl_ssi: Rename cpu_dai parameter to dai

2017-12-12 Thread Nicolin Chen
Shortens the variable name to save space, useful for dev_err outputs.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index d3bb662..69fa86d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -668,10 +668,10 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream 
*substream,
  *   (In 2-channel I2S Master mode, slot_width is fixed 32)
  */
 static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *cpu_dai,
+   struct snd_soc_dai *dai,
struct snd_pcm_hw_params *hw_params)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
@@ -701,7 +701,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
 * never greater than 1/5 IPG clock rate
 */
if (freq * 5 > clk_get_rate(ssi->clk)) {
-   dev_err(cpu_dai->dev, "bitclk > ipgclk / 5\n");
+   dev_err(dai->dev, "bitclk > ipgclk / 5\n");
return -EINVAL;
}
 
@@ -750,7 +750,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
 
/* No proper pm found if it is still remaining the initial value */
if (pm == 999) {
-   dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
+   dev_err(dai->dev, "failed to handle the required sysclk\n");
return -EINVAL;
}
 
@@ -766,7 +766,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
if (!baudclk_is_used) {
ret = clk_set_rate(ssi->baudclk, baudrate);
if (ret) {
-   dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
+   dev_err(dai->dev, "failed to set baudclk rate\n");
return -EINVAL;
}
}
@@ -787,9 +787,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
  */
 static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *hw_params,
-struct snd_soc_dai *cpu_dai)
+struct snd_soc_dai *dai)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
unsigned int channels = params_channels(hw_params);
unsigned int sample_size = params_width(hw_params);
@@ -806,7 +806,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-   ret = fsl_ssi_set_bclk(substream, cpu_dai, hw_params);
+   ret = fsl_ssi_set_bclk(substream, dai, hw_params);
if (ret)
return ret;
 
@@ -844,7 +844,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 }
 
 static int fsl_ssi_hw_free(struct snd_pcm_substream *substream,
-  struct snd_soc_dai *cpu_dai)
+  struct snd_soc_dai *dai)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
@@ -1013,30 +1013,30 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 /**
  * Configure Digital Audio Interface (DAI) Format
  */
-static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
/* AC97 configured DAIFMT earlier in the probe() */
if (fsl_ssi_is_ac97(ssi))
return 0;
 
-   return _fsl_ssi_set_dai_fmt(cpu_dai->dev, ssi, fmt);
+   return _fsl_ssi_set_dai_fmt(dai->dev, ssi, fmt);
 }
 
 /**
  * Set TDM slot number and slot width
  */
-static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
+static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
u32 rx_mask, int slots, int slot_width)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
u32 val;
 
/* The word length should be 8, 10, 12, 16, 18, 20, 22 or 24 */
if (slot_width & 1 || slot_width < 8 || slot_width > 24) {
-   dev_err(cpu_dai->dev, "invalid slot width: %d\n", 

[PATCH v2 05/11] ASoC: fsl_ssi: Refine indentations and wrappings

2017-12-12 Thread Nicolin Chen
This patch just simply unifies the coding style.

Signed-off-by: Nicolin Chen 
---

Changelog
v1->v2
 * Added two missing indentation changes
 * Removed two extra blank lines.

 sound/soc/fsl/fsl_ssi.c | 239 +---
 sound/soc/fsl/fsl_ssi.h |   2 +-
 sound/soc/fsl/fsl_ssi_dbg.c |   3 +-
 3 files changed, 118 insertions(+), 126 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 8b5407d..9a3db08 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -69,21 +69,35 @@
  * samples will be written to STX properly.
  */
 #ifdef __BIG_ENDIAN
-#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
-SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
-SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
+#define FSLSSI_I2S_FORMATS \
+   (SNDRV_PCM_FMTBIT_S8 | \
+SNDRV_PCM_FMTBIT_S16_BE | \
+SNDRV_PCM_FMTBIT_S18_3BE | \
+SNDRV_PCM_FMTBIT_S20_3BE | \
+SNDRV_PCM_FMTBIT_S24_3BE | \
+SNDRV_PCM_FMTBIT_S24_BE)
 #else
-#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
-SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
+#define FSLSSI_I2S_FORMATS \
+   (SNDRV_PCM_FMTBIT_S8 | \
+SNDRV_PCM_FMTBIT_S16_LE | \
+SNDRV_PCM_FMTBIT_S18_3LE | \
+SNDRV_PCM_FMTBIT_S20_3LE | \
+SNDRV_PCM_FMTBIT_S24_3LE | \
+SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
-#define FSLSSI_SIER_DBG_RX_FLAGS (SSI_SIER_RFF0_EN | \
-   SSI_SIER_RLS_EN | SSI_SIER_RFS_EN | \
-   SSI_SIER_ROE0_EN | SSI_SIER_RFRC_EN)
-#define FSLSSI_SIER_DBG_TX_FLAGS (SSI_SIER_TFE0_EN | \
-   SSI_SIER_TLS_EN | SSI_SIER_TFS_EN | \
-   SSI_SIER_TUE0_EN | SSI_SIER_TFRC_EN)
+#define FSLSSI_SIER_DBG_RX_FLAGS \
+   (SSI_SIER_RFF0_EN | \
+SSI_SIER_RLS_EN | \
+SSI_SIER_RFS_EN | \
+SSI_SIER_ROE0_EN | \
+SSI_SIER_RFRC_EN)
+#define FSLSSI_SIER_DBG_TX_FLAGS \
+   (SSI_SIER_TFE0_EN | \
+SSI_SIER_TLS_EN | \
+SSI_SIER_TFS_EN | \
+SSI_SIER_TUE0_EN | \
+SSI_SIER_TFRC_EN)
 
 enum fsl_ssi_type {
FSL_SSI_MCP8610,
@@ -291,8 +305,8 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
.imx = false,
.offline_config = true,
.sisr_write_mask = SSI_SISR_RFRC | SSI_SISR_TFRC |
-   SSI_SISR_ROE0 | SSI_SISR_ROE1 |
-   SSI_SISR_TUE0 | SSI_SISR_TUE1,
+  SSI_SISR_ROE0 | SSI_SISR_ROE1 |
+  SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
@@ -306,15 +320,15 @@ static struct fsl_ssi_soc_data fsl_ssi_imx35 = {
.imx = true,
.offline_config = true,
.sisr_write_mask = SSI_SISR_RFRC | SSI_SISR_TFRC |
-   SSI_SISR_ROE0 | SSI_SISR_ROE1 |
-   SSI_SISR_TUE0 | SSI_SISR_TUE1,
+  SSI_SISR_ROE0 | SSI_SISR_ROE1 |
+  SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static struct fsl_ssi_soc_data fsl_ssi_imx51 = {
.imx = true,
.offline_config = false,
.sisr_write_mask = SSI_SISR_ROE0 | SSI_SISR_ROE1 |
-   SSI_SISR_TUE0 | SSI_SISR_TUE1,
+  SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static const struct of_device_id fsl_ssi_ids[] = {
@@ -373,21 +387,21 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 
if (enable) {
regmap_update_bits(regs, REG_SSI_SIER,
-   vals->rx.sier | vals->tx.sier,
-   vals->rx.sier | vals->tx.sier);
+  vals->rx.sier | vals->tx.sier,
+  vals->rx.sier | vals->tx.sier);
regmap_update_bits(regs, REG_SSI_SRCR,
-   vals->rx.srcr | vals->tx.srcr,
-   vals->rx.srcr | vals->tx.srcr);
+  vals->rx.srcr | vals->tx.srcr,
+  vals->rx.srcr | vals->tx.srcr);
regmap_update_bits(regs, REG_SSI_STCR,
-   vals->rx.stcr | vals->tx.stcr,
-   vals->rx.stcr | vals->tx.stcr);
+  vals->rx.stcr | vals->tx.stcr,
+  vals->rx.stcr | vals->tx.stcr);
} else {
regmap_update_bits(regs, REG_SSI_SRCR,
-   vals->rx.srcr | vals->tx.srcr, 0);
+  vals->rx.srcr | vals->tx.srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR,
-   vals->rx.stcr | vals->tx.stcr, 0);
+  vals->rx.stcr | vals->tx.stcr, 0);
  

[PATCH v2 07/11] ASoC: fsl_ssi: Rename cpu_dai parameter to dai

2017-12-12 Thread Nicolin Chen
Shortens the variable name to save space, useful for dev_err outputs.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index d3bb662..69fa86d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -668,10 +668,10 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream 
*substream,
  *   (In 2-channel I2S Master mode, slot_width is fixed 32)
  */
 static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *cpu_dai,
+   struct snd_soc_dai *dai,
struct snd_pcm_hw_params *hw_params)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
@@ -701,7 +701,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
 * never greater than 1/5 IPG clock rate
 */
if (freq * 5 > clk_get_rate(ssi->clk)) {
-   dev_err(cpu_dai->dev, "bitclk > ipgclk / 5\n");
+   dev_err(dai->dev, "bitclk > ipgclk / 5\n");
return -EINVAL;
}
 
@@ -750,7 +750,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
 
/* No proper pm found if it is still remaining the initial value */
if (pm == 999) {
-   dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
+   dev_err(dai->dev, "failed to handle the required sysclk\n");
return -EINVAL;
}
 
@@ -766,7 +766,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
if (!baudclk_is_used) {
ret = clk_set_rate(ssi->baudclk, baudrate);
if (ret) {
-   dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
+   dev_err(dai->dev, "failed to set baudclk rate\n");
return -EINVAL;
}
}
@@ -787,9 +787,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
  */
 static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *hw_params,
-struct snd_soc_dai *cpu_dai)
+struct snd_soc_dai *dai)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
unsigned int channels = params_channels(hw_params);
unsigned int sample_size = params_width(hw_params);
@@ -806,7 +806,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-   ret = fsl_ssi_set_bclk(substream, cpu_dai, hw_params);
+   ret = fsl_ssi_set_bclk(substream, dai, hw_params);
if (ret)
return ret;
 
@@ -844,7 +844,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 }
 
 static int fsl_ssi_hw_free(struct snd_pcm_substream *substream,
-  struct snd_soc_dai *cpu_dai)
+  struct snd_soc_dai *dai)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
@@ -1013,30 +1013,30 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 /**
  * Configure Digital Audio Interface (DAI) Format
  */
-static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
/* AC97 configured DAIFMT earlier in the probe() */
if (fsl_ssi_is_ac97(ssi))
return 0;
 
-   return _fsl_ssi_set_dai_fmt(cpu_dai->dev, ssi, fmt);
+   return _fsl_ssi_set_dai_fmt(dai->dev, ssi, fmt);
 }
 
 /**
  * Set TDM slot number and slot width
  */
-static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
+static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
u32 rx_mask, int slots, int slot_width)
 {
-   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+   struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
u32 val;
 
/* The word length should be 8, 10, 12, 16, 18, 20, 22 or 24 */
if (slot_width & 1 || slot_width < 8 || slot_width > 24) {
-   dev_err(cpu_dai->dev, "invalid slot width: %d\n", slot_width);
+

[PATCH v2 05/11] ASoC: fsl_ssi: Refine indentations and wrappings

2017-12-12 Thread Nicolin Chen
This patch just simply unifies the coding style.

Signed-off-by: Nicolin Chen 
---

Changelog
v1->v2
 * Added two missing indentation changes
 * Removed two extra blank lines.

 sound/soc/fsl/fsl_ssi.c | 239 +---
 sound/soc/fsl/fsl_ssi.h |   2 +-
 sound/soc/fsl/fsl_ssi_dbg.c |   3 +-
 3 files changed, 118 insertions(+), 126 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 8b5407d..9a3db08 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -69,21 +69,35 @@
  * samples will be written to STX properly.
  */
 #ifdef __BIG_ENDIAN
-#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
-SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
-SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
+#define FSLSSI_I2S_FORMATS \
+   (SNDRV_PCM_FMTBIT_S8 | \
+SNDRV_PCM_FMTBIT_S16_BE | \
+SNDRV_PCM_FMTBIT_S18_3BE | \
+SNDRV_PCM_FMTBIT_S20_3BE | \
+SNDRV_PCM_FMTBIT_S24_3BE | \
+SNDRV_PCM_FMTBIT_S24_BE)
 #else
-#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
-SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
+#define FSLSSI_I2S_FORMATS \
+   (SNDRV_PCM_FMTBIT_S8 | \
+SNDRV_PCM_FMTBIT_S16_LE | \
+SNDRV_PCM_FMTBIT_S18_3LE | \
+SNDRV_PCM_FMTBIT_S20_3LE | \
+SNDRV_PCM_FMTBIT_S24_3LE | \
+SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
-#define FSLSSI_SIER_DBG_RX_FLAGS (SSI_SIER_RFF0_EN | \
-   SSI_SIER_RLS_EN | SSI_SIER_RFS_EN | \
-   SSI_SIER_ROE0_EN | SSI_SIER_RFRC_EN)
-#define FSLSSI_SIER_DBG_TX_FLAGS (SSI_SIER_TFE0_EN | \
-   SSI_SIER_TLS_EN | SSI_SIER_TFS_EN | \
-   SSI_SIER_TUE0_EN | SSI_SIER_TFRC_EN)
+#define FSLSSI_SIER_DBG_RX_FLAGS \
+   (SSI_SIER_RFF0_EN | \
+SSI_SIER_RLS_EN | \
+SSI_SIER_RFS_EN | \
+SSI_SIER_ROE0_EN | \
+SSI_SIER_RFRC_EN)
+#define FSLSSI_SIER_DBG_TX_FLAGS \
+   (SSI_SIER_TFE0_EN | \
+SSI_SIER_TLS_EN | \
+SSI_SIER_TFS_EN | \
+SSI_SIER_TUE0_EN | \
+SSI_SIER_TFRC_EN)
 
 enum fsl_ssi_type {
FSL_SSI_MCP8610,
@@ -291,8 +305,8 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
.imx = false,
.offline_config = true,
.sisr_write_mask = SSI_SISR_RFRC | SSI_SISR_TFRC |
-   SSI_SISR_ROE0 | SSI_SISR_ROE1 |
-   SSI_SISR_TUE0 | SSI_SISR_TUE1,
+  SSI_SISR_ROE0 | SSI_SISR_ROE1 |
+  SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
@@ -306,15 +320,15 @@ static struct fsl_ssi_soc_data fsl_ssi_imx35 = {
.imx = true,
.offline_config = true,
.sisr_write_mask = SSI_SISR_RFRC | SSI_SISR_TFRC |
-   SSI_SISR_ROE0 | SSI_SISR_ROE1 |
-   SSI_SISR_TUE0 | SSI_SISR_TUE1,
+  SSI_SISR_ROE0 | SSI_SISR_ROE1 |
+  SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static struct fsl_ssi_soc_data fsl_ssi_imx51 = {
.imx = true,
.offline_config = false,
.sisr_write_mask = SSI_SISR_ROE0 | SSI_SISR_ROE1 |
-   SSI_SISR_TUE0 | SSI_SISR_TUE1,
+  SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static const struct of_device_id fsl_ssi_ids[] = {
@@ -373,21 +387,21 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 
if (enable) {
regmap_update_bits(regs, REG_SSI_SIER,
-   vals->rx.sier | vals->tx.sier,
-   vals->rx.sier | vals->tx.sier);
+  vals->rx.sier | vals->tx.sier,
+  vals->rx.sier | vals->tx.sier);
regmap_update_bits(regs, REG_SSI_SRCR,
-   vals->rx.srcr | vals->tx.srcr,
-   vals->rx.srcr | vals->tx.srcr);
+  vals->rx.srcr | vals->tx.srcr,
+  vals->rx.srcr | vals->tx.srcr);
regmap_update_bits(regs, REG_SSI_STCR,
-   vals->rx.stcr | vals->tx.stcr,
-   vals->rx.stcr | vals->tx.stcr);
+  vals->rx.stcr | vals->tx.stcr,
+  vals->rx.stcr | vals->tx.stcr);
} else {
regmap_update_bits(regs, REG_SSI_SRCR,
-   vals->rx.srcr | vals->tx.srcr, 0);
+  vals->rx.srcr | vals->tx.srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR,
-   vals->rx.stcr | vals->tx.stcr, 0);
+  vals->rx.stcr | vals->tx.stcr, 0);

[PATCH v2 02/11] ASoC: fsl_ssi: Cache pdev->dev pointer

2017-12-12 Thread Nicolin Chen
There should be no trouble to understand dev = pdev->dev.
This can save some space to have more print info or save
some wrapped lines.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 64 -
 1 file changed, 31 insertions(+), 33 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 84d2f7e..e903c92 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1379,23 +1379,24 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
struct fsl_ssi *ssi, void __iomem *iomem)
 {
struct device_node *np = pdev->dev.of_node;
+   struct device *dev = >dev;
u32 dmas[4];
int ret;
 
if (ssi->has_ipg_clk_name)
-   ssi->clk = devm_clk_get(>dev, "ipg");
+   ssi->clk = devm_clk_get(dev, "ipg");
else
-   ssi->clk = devm_clk_get(>dev, NULL);
+   ssi->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ssi->clk)) {
ret = PTR_ERR(ssi->clk);
-   dev_err(>dev, "could not get clock: %d\n", ret);
+   dev_err(dev, "could not get clock: %d\n", ret);
return ret;
}
 
if (!ssi->has_ipg_clk_name) {
ret = clk_prepare_enable(ssi->clk);
if (ret) {
-   dev_err(>dev, "clk_prepare_enable failed: %d\n", 
ret);
+   dev_err(dev, "clk_prepare_enable failed: %d\n", ret);
return ret;
}
}
@@ -1403,9 +1404,9 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
/* For those SLAVE implementations, we ignore non-baudclk cases
 * and, instead, abandon MASTER mode that needs baud clock.
 */
-   ssi->baudclk = devm_clk_get(>dev, "baud");
+   ssi->baudclk = devm_clk_get(dev, "baud");
if (IS_ERR(ssi->baudclk))
-   dev_dbg(>dev, "could not get baud clock: %ld\n",
+   dev_dbg(dev, "could not get baud clock: %ld\n",
 PTR_ERR(ssi->baudclk));
 
ssi->dma_params_tx.maxburst = ssi->dma_maxburst;
@@ -1469,6 +1470,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
struct fsl_ssi *ssi;
int ret = 0;
struct device_node *np = pdev->dev.of_node;
+   struct device *dev = >dev;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
@@ -1477,17 +1479,16 @@ static int fsl_ssi_probe(struct platform_device *pdev)
char name[64];
struct regmap_config regconfig = fsl_ssi_regconfig;
 
-   of_id = of_match_device(fsl_ssi_ids, >dev);
+   of_id = of_match_device(fsl_ssi_ids, dev);
if (!of_id || !of_id->data)
return -EINVAL;
 
-   ssi = devm_kzalloc(>dev, sizeof(*ssi),
-   GFP_KERNEL);
+   ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
if (!ssi)
return -ENOMEM;
 
ssi->soc = of_id->data;
-   ssi->dev = >dev;
+   ssi->dev = dev;
 
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
@@ -1507,10 +1508,10 @@ static int fsl_ssi_probe(struct platform_device *pdev)
memcpy(>cpu_dai_drv, _ssi_dai_template,
   sizeof(fsl_ssi_dai_template));
}
-   ssi->cpu_dai_drv.name = dev_name(>dev);
+   ssi->cpu_dai_drv.name = dev_name(dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   iomem = devm_ioremap_resource(>dev, res);
+   iomem = devm_ioremap_resource(dev, res);
if (IS_ERR(iomem))
return PTR_ERR(iomem);
ssi->ssi_phys = res->start;
@@ -1528,21 +1529,20 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ret = of_property_match_string(np, "clock-names", "ipg");
if (ret < 0) {
ssi->has_ipg_clk_name = false;
-   ssi->regs = devm_regmap_init_mmio(>dev, iomem,
-   );
+   ssi->regs = devm_regmap_init_mmio(dev, iomem, );
} else {
ssi->has_ipg_clk_name = true;
-   ssi->regs = devm_regmap_init_mmio_clk(>dev,
-   "ipg", iomem, );
+   ssi->regs = devm_regmap_init_mmio_clk(dev, "ipg", iomem,
+ );
}
if (IS_ERR(ssi->regs)) {
-   dev_err(>dev, "Failed to init register map\n");
+   dev_err(dev, "Failed to init register map\n");
return PTR_ERR(ssi->regs);
}
 
ssi->irq = platform_get_irq(pdev, 0);
if (ssi->irq < 0) {
-   dev_err(>dev, "no irq for node %s\n", pdev->name);
+   dev_err(dev, "no irq for node %s\n", pdev->name);
return ssi->irq;
}
 
@@ -1605,7 +1605,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)

[PATCH v2 02/11] ASoC: fsl_ssi: Cache pdev->dev pointer

2017-12-12 Thread Nicolin Chen
There should be no trouble to understand dev = pdev->dev.
This can save some space to have more print info or save
some wrapped lines.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 64 -
 1 file changed, 31 insertions(+), 33 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 84d2f7e..e903c92 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1379,23 +1379,24 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
struct fsl_ssi *ssi, void __iomem *iomem)
 {
struct device_node *np = pdev->dev.of_node;
+   struct device *dev = >dev;
u32 dmas[4];
int ret;
 
if (ssi->has_ipg_clk_name)
-   ssi->clk = devm_clk_get(>dev, "ipg");
+   ssi->clk = devm_clk_get(dev, "ipg");
else
-   ssi->clk = devm_clk_get(>dev, NULL);
+   ssi->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ssi->clk)) {
ret = PTR_ERR(ssi->clk);
-   dev_err(>dev, "could not get clock: %d\n", ret);
+   dev_err(dev, "could not get clock: %d\n", ret);
return ret;
}
 
if (!ssi->has_ipg_clk_name) {
ret = clk_prepare_enable(ssi->clk);
if (ret) {
-   dev_err(>dev, "clk_prepare_enable failed: %d\n", 
ret);
+   dev_err(dev, "clk_prepare_enable failed: %d\n", ret);
return ret;
}
}
@@ -1403,9 +1404,9 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
/* For those SLAVE implementations, we ignore non-baudclk cases
 * and, instead, abandon MASTER mode that needs baud clock.
 */
-   ssi->baudclk = devm_clk_get(>dev, "baud");
+   ssi->baudclk = devm_clk_get(dev, "baud");
if (IS_ERR(ssi->baudclk))
-   dev_dbg(>dev, "could not get baud clock: %ld\n",
+   dev_dbg(dev, "could not get baud clock: %ld\n",
 PTR_ERR(ssi->baudclk));
 
ssi->dma_params_tx.maxburst = ssi->dma_maxburst;
@@ -1469,6 +1470,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
struct fsl_ssi *ssi;
int ret = 0;
struct device_node *np = pdev->dev.of_node;
+   struct device *dev = >dev;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
@@ -1477,17 +1479,16 @@ static int fsl_ssi_probe(struct platform_device *pdev)
char name[64];
struct regmap_config regconfig = fsl_ssi_regconfig;
 
-   of_id = of_match_device(fsl_ssi_ids, >dev);
+   of_id = of_match_device(fsl_ssi_ids, dev);
if (!of_id || !of_id->data)
return -EINVAL;
 
-   ssi = devm_kzalloc(>dev, sizeof(*ssi),
-   GFP_KERNEL);
+   ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
if (!ssi)
return -ENOMEM;
 
ssi->soc = of_id->data;
-   ssi->dev = >dev;
+   ssi->dev = dev;
 
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
@@ -1507,10 +1508,10 @@ static int fsl_ssi_probe(struct platform_device *pdev)
memcpy(>cpu_dai_drv, _ssi_dai_template,
   sizeof(fsl_ssi_dai_template));
}
-   ssi->cpu_dai_drv.name = dev_name(>dev);
+   ssi->cpu_dai_drv.name = dev_name(dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   iomem = devm_ioremap_resource(>dev, res);
+   iomem = devm_ioremap_resource(dev, res);
if (IS_ERR(iomem))
return PTR_ERR(iomem);
ssi->ssi_phys = res->start;
@@ -1528,21 +1529,20 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ret = of_property_match_string(np, "clock-names", "ipg");
if (ret < 0) {
ssi->has_ipg_clk_name = false;
-   ssi->regs = devm_regmap_init_mmio(>dev, iomem,
-   );
+   ssi->regs = devm_regmap_init_mmio(dev, iomem, );
} else {
ssi->has_ipg_clk_name = true;
-   ssi->regs = devm_regmap_init_mmio_clk(>dev,
-   "ipg", iomem, );
+   ssi->regs = devm_regmap_init_mmio_clk(dev, "ipg", iomem,
+ );
}
if (IS_ERR(ssi->regs)) {
-   dev_err(>dev, "Failed to init register map\n");
+   dev_err(dev, "Failed to init register map\n");
return PTR_ERR(ssi->regs);
}
 
ssi->irq = platform_get_irq(pdev, 0);
if (ssi->irq < 0) {
-   dev_err(>dev, "no irq for node %s\n", pdev->name);
+   dev_err(dev, "no irq for node %s\n", pdev->name);
return ssi->irq;
}
 
@@ -1605,7 +1605,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
break;
}
 
- 

[PATCH v2 09/11] ASoC: fsl_ssi: Replace fsl_ssi_rxtx_reg_val with fsl_ssi_regvals

2017-12-12 Thread Nicolin Chen
The name fsl_ssi_rxtx_reg_val is too long to read comfortably.
So this patch shortens it by using an array (fsl_ssi_regvals,
renamed from fsl_ssi_reg_val). To do that, it also introduces
two macros (TX and RX) to replace the wrapper structure. This
will also help further cleanups.

Meanwhile, it unifies all local variable with the name "vals"
to get rid of the name "reg" -- could be confusing with "regs"
in the private struct for regmap.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 79 +++--
 sound/soc/fsl/fsl_ssi.h |  3 ++
 2 files changed, 40 insertions(+), 42 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7fcc6bd..7a8a768 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -106,18 +106,13 @@ enum fsl_ssi_type {
FSL_SSI_MX51,
 };
 
-struct fsl_ssi_reg_val {
+struct fsl_ssi_regvals {
u32 sier;
u32 srcr;
u32 stcr;
u32 scr;
 };
 
-struct fsl_ssi_rxtx_reg_val {
-   struct fsl_ssi_reg_val rx;
-   struct fsl_ssi_reg_val tx;
-};
-
 static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
@@ -213,7 +208,7 @@ struct fsl_ssi_soc_data {
  * @fifo_depth: Depth of the SSI FIFOs
  * @slot_width: Width of each DAI slot
  * @slots: Number of slots
- * @rxtx_reg_val: Specific RX/TX register settings
+ * @regvals: Specific RX/TX register settings
  *
  * @clk: Clock source to access register
  * @baudclk: Clock source to generate bit and frame-sync clocks
@@ -257,7 +252,7 @@ struct fsl_ssi {
unsigned int fifo_depth;
unsigned int slot_width;
unsigned int slots;
-   struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
+   struct fsl_ssi_regvals regvals[2];
 
struct clk *clk;
struct clk *baudclk;
@@ -383,25 +378,25 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
 {
struct regmap *regs = ssi->regs;
-   struct fsl_ssi_rxtx_reg_val *vals = >rxtx_reg_val;
+   struct fsl_ssi_regvals *vals = ssi->regvals;
 
if (enable) {
regmap_update_bits(regs, REG_SSI_SIER,
-  vals->rx.sier | vals->tx.sier,
-  vals->rx.sier | vals->tx.sier);
+  vals[RX].sier | vals[TX].sier,
+  vals[RX].sier | vals[TX].sier);
regmap_update_bits(regs, REG_SSI_SRCR,
-  vals->rx.srcr | vals->tx.srcr,
-  vals->rx.srcr | vals->tx.srcr);
+  vals[RX].srcr | vals[TX].srcr,
+  vals[RX].srcr | vals[TX].srcr);
regmap_update_bits(regs, REG_SSI_STCR,
-  vals->rx.stcr | vals->tx.stcr,
-  vals->rx.stcr | vals->tx.stcr);
+  vals[RX].stcr | vals[TX].stcr,
+  vals[RX].stcr | vals[TX].stcr);
} else {
regmap_update_bits(regs, REG_SSI_SRCR,
-  vals->rx.srcr | vals->tx.srcr, 0);
+  vals[RX].srcr | vals[TX].srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR,
-  vals->rx.stcr | vals->tx.stcr, 0);
+  vals[RX].stcr | vals[TX].stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER,
-  vals->rx.sier | vals->tx.sier, 0);
+  vals[RX].sier | vals[TX].sier, 0);
}
 }
 
@@ -443,10 +438,10 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
  * Enable or disable SSI configuration.
  */
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
-  struct fsl_ssi_reg_val *vals)
+  struct fsl_ssi_regvals *vals)
 {
struct regmap *regs = ssi->regs;
-   struct fsl_ssi_reg_val *avals;
+   struct fsl_ssi_regvals *avals;
int nr_active_streams;
u32 scr;
int keep_active;
@@ -461,10 +456,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
keep_active = 0;
 
/* Get the opposite direction to keep its values untouched */
-   if (>rxtx_reg_val.rx == vals)
-   avals = >rxtx_reg_val.tx;
+   if (>regvals[RX] == vals)
+   avals = >regvals[TX];
else
-   avals = >rxtx_reg_val.rx;
+   avals = >regvals[RX];
 
if (!enable) {
/* Exclude necessary bits for the opposite stream */
@@ -543,7 +538,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
 static void fsl_ssi_rx_config(struct fsl_ssi *ssi, bool enable)
 {
-   fsl_ssi_config(ssi, enable, 

[PATCH v2 09/11] ASoC: fsl_ssi: Replace fsl_ssi_rxtx_reg_val with fsl_ssi_regvals

2017-12-12 Thread Nicolin Chen
The name fsl_ssi_rxtx_reg_val is too long to read comfortably.
So this patch shortens it by using an array (fsl_ssi_regvals,
renamed from fsl_ssi_reg_val). To do that, it also introduces
two macros (TX and RX) to replace the wrapper structure. This
will also help further cleanups.

Meanwhile, it unifies all local variable with the name "vals"
to get rid of the name "reg" -- could be confusing with "regs"
in the private struct for regmap.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 79 +++--
 sound/soc/fsl/fsl_ssi.h |  3 ++
 2 files changed, 40 insertions(+), 42 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7fcc6bd..7a8a768 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -106,18 +106,13 @@ enum fsl_ssi_type {
FSL_SSI_MX51,
 };
 
-struct fsl_ssi_reg_val {
+struct fsl_ssi_regvals {
u32 sier;
u32 srcr;
u32 stcr;
u32 scr;
 };
 
-struct fsl_ssi_rxtx_reg_val {
-   struct fsl_ssi_reg_val rx;
-   struct fsl_ssi_reg_val tx;
-};
-
 static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
@@ -213,7 +208,7 @@ struct fsl_ssi_soc_data {
  * @fifo_depth: Depth of the SSI FIFOs
  * @slot_width: Width of each DAI slot
  * @slots: Number of slots
- * @rxtx_reg_val: Specific RX/TX register settings
+ * @regvals: Specific RX/TX register settings
  *
  * @clk: Clock source to access register
  * @baudclk: Clock source to generate bit and frame-sync clocks
@@ -257,7 +252,7 @@ struct fsl_ssi {
unsigned int fifo_depth;
unsigned int slot_width;
unsigned int slots;
-   struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
+   struct fsl_ssi_regvals regvals[2];
 
struct clk *clk;
struct clk *baudclk;
@@ -383,25 +378,25 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
 {
struct regmap *regs = ssi->regs;
-   struct fsl_ssi_rxtx_reg_val *vals = >rxtx_reg_val;
+   struct fsl_ssi_regvals *vals = ssi->regvals;
 
if (enable) {
regmap_update_bits(regs, REG_SSI_SIER,
-  vals->rx.sier | vals->tx.sier,
-  vals->rx.sier | vals->tx.sier);
+  vals[RX].sier | vals[TX].sier,
+  vals[RX].sier | vals[TX].sier);
regmap_update_bits(regs, REG_SSI_SRCR,
-  vals->rx.srcr | vals->tx.srcr,
-  vals->rx.srcr | vals->tx.srcr);
+  vals[RX].srcr | vals[TX].srcr,
+  vals[RX].srcr | vals[TX].srcr);
regmap_update_bits(regs, REG_SSI_STCR,
-  vals->rx.stcr | vals->tx.stcr,
-  vals->rx.stcr | vals->tx.stcr);
+  vals[RX].stcr | vals[TX].stcr,
+  vals[RX].stcr | vals[TX].stcr);
} else {
regmap_update_bits(regs, REG_SSI_SRCR,
-  vals->rx.srcr | vals->tx.srcr, 0);
+  vals[RX].srcr | vals[TX].srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR,
-  vals->rx.stcr | vals->tx.stcr, 0);
+  vals[RX].stcr | vals[TX].stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER,
-  vals->rx.sier | vals->tx.sier, 0);
+  vals[RX].sier | vals[TX].sier, 0);
}
 }
 
@@ -443,10 +438,10 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
  * Enable or disable SSI configuration.
  */
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
-  struct fsl_ssi_reg_val *vals)
+  struct fsl_ssi_regvals *vals)
 {
struct regmap *regs = ssi->regs;
-   struct fsl_ssi_reg_val *avals;
+   struct fsl_ssi_regvals *avals;
int nr_active_streams;
u32 scr;
int keep_active;
@@ -461,10 +456,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
keep_active = 0;
 
/* Get the opposite direction to keep its values untouched */
-   if (>rxtx_reg_val.rx == vals)
-   avals = >rxtx_reg_val.tx;
+   if (>regvals[RX] == vals)
+   avals = >regvals[TX];
else
-   avals = >rxtx_reg_val.rx;
+   avals = >regvals[RX];
 
if (!enable) {
/* Exclude necessary bits for the opposite stream */
@@ -543,7 +538,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
 static void fsl_ssi_rx_config(struct fsl_ssi *ssi, bool enable)
 {
-   fsl_ssi_config(ssi, enable, >rxtx_reg_val.rx);
+   

[PATCH v2 11/11] ASoC: fsl_ssi: Define ternary macros to simplify code

2017-12-12 Thread Nicolin Chen
Some regmap code looks redudant. So simplify it.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 27 +++
 sound/soc/fsl/fsl_ssi.h |  4 
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index dd091eb..5b4fa43 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -405,13 +405,10 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
  */
 static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
 {
-   if (is_rx) {
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_RX_CLR, SSI_SOR_RX_CLR);
-   } else {
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_TX_CLR, SSI_SOR_TX_CLR);
-   }
+   bool tx = !is_rx;
+
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 }
 
 /**
@@ -666,6 +663,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
struct snd_soc_dai *dai,
struct snd_pcm_hw_params *hw_params)
 {
+   bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
@@ -753,10 +751,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
(psr ? SSI_SxCCR_PSR : 0);
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || synchronous)
-   regmap_update_bits(regs, REG_SSI_STCCR, mask, stccr);
-   else
-   regmap_update_bits(regs, REG_SSI_SRCCR, mask, stccr);
+   /* STCCR is used for RX in synchronous mode */
+   tx2 = tx || synchronous;
+   regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
ret = clk_set_rate(ssi->baudclk, baudrate);
@@ -784,6 +781,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 struct snd_pcm_hw_params *hw_params,
 struct snd_soc_dai *dai)
 {
+   bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
unsigned int channels = params_channels(hw_params);
@@ -829,11 +827,8 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
-   ssi->cpu_dai_drv.symmetric_rates)
-   regmap_update_bits(regs, REG_SSI_STCCR, SSI_SxCCR_WL_MASK, wl);
-   else
-   regmap_update_bits(regs, REG_SSI_SRCCR, SSI_SxCCR_WL_MASK, wl);
+   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
 }
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index b610087..de2fdc5 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -35,10 +35,12 @@
 #define REG_SSI_STCR   0x1c
 /* SSI Receive Configuration Register */
 #define REG_SSI_SRCR   0x20
+#define REG_SSI_SxCR(tx)   ((tx) ? REG_SSI_STCR : REG_SSI_SRCR)
 /* SSI Transmit Clock Control Register */
 #define REG_SSI_STCCR  0x24
 /* SSI Receive Clock Control Register */
 #define REG_SSI_SRCCR  0x28
+#define REG_SSI_SxCCR(tx)  ((tx) ? REG_SSI_STCCR : REG_SSI_SRCCR)
 /* SSI FIFO Control/Status Register */
 #define REG_SSI_SFCSR  0x2c
 /*
@@ -67,6 +69,7 @@
 #define REG_SSI_STMSK  0x48
 /* SSI  Receive Time Slot Mask Register */
 #define REG_SSI_SRMSK  0x4c
+#define REG_SSI_SxMSK(tx)  ((tx) ? REG_SSI_STMSK : REG_SSI_SRMSK)
 /*
  * SSI AC97 Channel Status Register
  *
@@ -249,6 +252,7 @@
 #define SSI_SOR_CLKOFF 0x0040
 #define SSI_SOR_RX_CLR 0x0020
 #define SSI_SOR_TX_CLR 0x0010
+#define SSI_SOR_xX_CLR(tx) ((tx) ? SSI_SOR_TX_CLR : SSI_SOR_RX_CLR)
 #define SSI_SOR_INIT   0x0008
 #define SSI_SOR_WAIT_SHIFT 1
 #define SSI_SOR_WAIT_MASK  0x0006
-- 
2.7.4



[PATCH v2 11/11] ASoC: fsl_ssi: Define ternary macros to simplify code

2017-12-12 Thread Nicolin Chen
Some regmap code looks redudant. So simplify it.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 27 +++
 sound/soc/fsl/fsl_ssi.h |  4 
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index dd091eb..5b4fa43 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -405,13 +405,10 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
  */
 static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
 {
-   if (is_rx) {
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_RX_CLR, SSI_SOR_RX_CLR);
-   } else {
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_TX_CLR, SSI_SOR_TX_CLR);
-   }
+   bool tx = !is_rx;
+
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 }
 
 /**
@@ -666,6 +663,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
struct snd_soc_dai *dai,
struct snd_pcm_hw_params *hw_params)
 {
+   bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
@@ -753,10 +751,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
(psr ? SSI_SxCCR_PSR : 0);
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || synchronous)
-   regmap_update_bits(regs, REG_SSI_STCCR, mask, stccr);
-   else
-   regmap_update_bits(regs, REG_SSI_SRCCR, mask, stccr);
+   /* STCCR is used for RX in synchronous mode */
+   tx2 = tx || synchronous;
+   regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
ret = clk_set_rate(ssi->baudclk, baudrate);
@@ -784,6 +781,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 struct snd_pcm_hw_params *hw_params,
 struct snd_soc_dai *dai)
 {
+   bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
unsigned int channels = params_channels(hw_params);
@@ -829,11 +827,8 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
-   ssi->cpu_dai_drv.symmetric_rates)
-   regmap_update_bits(regs, REG_SSI_STCCR, SSI_SxCCR_WL_MASK, wl);
-   else
-   regmap_update_bits(regs, REG_SSI_SRCCR, SSI_SxCCR_WL_MASK, wl);
+   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
 }
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index b610087..de2fdc5 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -35,10 +35,12 @@
 #define REG_SSI_STCR   0x1c
 /* SSI Receive Configuration Register */
 #define REG_SSI_SRCR   0x20
+#define REG_SSI_SxCR(tx)   ((tx) ? REG_SSI_STCR : REG_SSI_SRCR)
 /* SSI Transmit Clock Control Register */
 #define REG_SSI_STCCR  0x24
 /* SSI Receive Clock Control Register */
 #define REG_SSI_SRCCR  0x28
+#define REG_SSI_SxCCR(tx)  ((tx) ? REG_SSI_STCCR : REG_SSI_SRCCR)
 /* SSI FIFO Control/Status Register */
 #define REG_SSI_SFCSR  0x2c
 /*
@@ -67,6 +69,7 @@
 #define REG_SSI_STMSK  0x48
 /* SSI  Receive Time Slot Mask Register */
 #define REG_SSI_SRMSK  0x4c
+#define REG_SSI_SxMSK(tx)  ((tx) ? REG_SSI_STMSK : REG_SSI_SRMSK)
 /*
  * SSI AC97 Channel Status Register
  *
@@ -249,6 +252,7 @@
 #define SSI_SOR_CLKOFF 0x0040
 #define SSI_SOR_RX_CLR 0x0020
 #define SSI_SOR_TX_CLR 0x0010
+#define SSI_SOR_xX_CLR(tx) ((tx) ? SSI_SOR_TX_CLR : SSI_SOR_RX_CLR)
 #define SSI_SOR_INIT   0x0008
 #define SSI_SOR_WAIT_SHIFT 1
 #define SSI_SOR_WAIT_MASK  0x0006
-- 
2.7.4



[PATCH v2 08/11] ASoC: fsl_ssi: Rename scr_val to scr

2017-12-12 Thread Nicolin Chen
Simplify the variable name. This reduces one over-80-character line.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 69fa86d..7fcc6bd 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -448,12 +448,12 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
struct regmap *regs = ssi->regs;
struct fsl_ssi_reg_val *avals;
int nr_active_streams;
-   u32 scr_val;
+   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, _val);
+   regmap_read(regs, REG_SSI_SCR, );
 
-   nr_active_streams = !!(scr_val & SSI_SCR_TE) + !!(scr_val & SSI_SCR_RE);
+   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -795,11 +795,11 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
unsigned int sample_size = params_width(hw_params);
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
-   u32 scr_val;
+   u32 scr;
int enabled;
 
-   regmap_read(regs, REG_SSI_SCR, _val);
-   enabled = scr_val & SSI_SCR_SSIEN;
+   regmap_read(regs, REG_SSI_SCR, );
+   enabled = scr & SSI_SCR_SSIEN;
 
/* To support simultaneous TX and RX, bypass it if SSI is enabled */
if (enabled && ssi->cpu_dai_drv.symmetric_rates)
-- 
2.7.4



[PATCH v2 08/11] ASoC: fsl_ssi: Rename scr_val to scr

2017-12-12 Thread Nicolin Chen
Simplify the variable name. This reduces one over-80-character line.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 69fa86d..7fcc6bd 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -448,12 +448,12 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
struct regmap *regs = ssi->regs;
struct fsl_ssi_reg_val *avals;
int nr_active_streams;
-   u32 scr_val;
+   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, _val);
+   regmap_read(regs, REG_SSI_SCR, );
 
-   nr_active_streams = !!(scr_val & SSI_SCR_TE) + !!(scr_val & SSI_SCR_RE);
+   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -795,11 +795,11 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
unsigned int sample_size = params_width(hw_params);
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
-   u32 scr_val;
+   u32 scr;
int enabled;
 
-   regmap_read(regs, REG_SSI_SCR, _val);
-   enabled = scr_val & SSI_SCR_SSIEN;
+   regmap_read(regs, REG_SSI_SCR, );
+   enabled = scr & SSI_SCR_SSIEN;
 
/* To support simultaneous TX and RX, bypass it if SSI is enabled */
if (enabled && ssi->cpu_dai_drv.symmetric_rates)
-- 
2.7.4



[PATCH v2 03/11] ASoC: fsl_ssi: Refine all comments

2017-12-12 Thread Nicolin Chen
This patch refines the comments by:
1) Removing all out-of-date comments
2) Removing all not-so-useful comments
3) Unifying the styles of all comments
4) Simplifying over-descriptive comments
5) Adding comments to improve code readablity
6) Moving all register related comments to fsl_ssi.h
7) Adding comments to all register and field defines

Signed-off-by: Nicolin Chen 
---

Changelog
v1->v2
 * Added some new comments at "SoC specific data" to be more precise.
 * Revised one comment in fsl_ssi_config().
 * Revised the comment of fsl_ssi_setup_reg_vals().
 * Added one comment for AC97 in fsl_ssi_setup_reg_vals().
 * Revised the comment of fsl_ssi_hw_params() to be more precise.
 * Added some comments in _fsl_ssi_set_dai_fmt() to help understand the formats.
 * Added one comment in fsl_ssi_set_dai_fmt() to state why AC97 needs to bypass 
it.
 * Revised comments in fsl_ssi_set_dai_tdm_slot() to be more precise.
 * Revised comments around dual FIFO code in fsl_ssi_imx_probe() to be more 
precise.

 sound/soc/fsl/fsl_ssi.c | 376 ++--
 sound/soc/fsl/fsl_ssi.h |  67 +++-
 sound/soc/fsl/fsl_ssi_dbg.c |  12 +-
 3 files changed, 188 insertions(+), 267 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e903c92..796a7ea 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -187,42 +187,48 @@ struct fsl_ssi_soc_data {
 /**
  * fsl_ssi: per-SSI private data
  *
- * @reg: Pointer to the regmap registers
+ * @regs: Pointer to the regmap registers
  * @irq: IRQ of this SSI
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
- * @i2s_mode: i2s and network mode configuration of the device. Is used to
- * switch between normal and i2s/network mode
- * mode depending on the number of channels
+ * @i2s_mode: I2S and Network mode configuration of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
- * @use_dual_fifo: DMA with support for both FIFOs used
- * @fifo_deph: Depth of the SSI FIFOs
- * @slot_width: width of each DAI slot
- * @slots: number of slots
- * @rxtx_reg_val: Specific register settings for receive/transmit configuration
+ * @use_dual_fifo: DMA with support for dual FIFO mode
+ * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
+ * @fifo_depth: Depth of the SSI FIFOs
+ * @slot_width: Width of each DAI slot
+ * @slots: Number of slots
+ * @rxtx_reg_val: Specific RX/TX register settings
  *
- * @clk: SSI clock
- * @baudclk: SSI baud clock for master mode
+ * @clk: Clock source to access register
+ * @baudclk: Clock source to generate bit and frame-sync clocks
  * @baudclk_streams: Active streams that are using baudclk
  *
+ * @regcache_sfcsr: Cache sfcsr register value during suspend and resume
+ * @regcache_sacnt: Cache sacnt register value during suspend and resume
+ *
  * @dma_params_tx: DMA transmit parameters
  * @dma_params_rx: DMA receive parameters
  * @ssi_phys: physical address of the SSI registers
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev used for deprecated fsl-ssi sound card
+ * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
+ *TODO: Should be replaced with simple-sound-card
  *
  * @dbg_stats: Debugging statistics
  *
  * @soc: SoC specific data
+ * @dev: Pointer to >dev
+ *
+ * @fifo_watermark: The FIFO watermark setting. Notifies DMA when there are
+ *  @fifo_watermark or fewer words in TX fifo or
+ *  @fifo_watermark or more empty words in RX fifo.
+ * @dma_maxburst: Max number of words to transfer in one go. So far,
+ *this is always the same as fifo_watermark.
  *
- * @fifo_watermark: the FIFO watermark setting.  Notifies DMA when
- * there are @fifo_watermark or fewer words in TX fifo or
- * @fifo_watermark or more empty words in RX fifo.
- * @dma_maxburst: max number of words to transfer in one go.  So far,
- * this is always the same as fifo_watermark.
+ * @ac97_reg_lock: Mutex lock to serialize AC97 register access operations
  */
 struct fsl_ssi {
struct regmap *regs;
@@ -243,20 +249,15 @@ struct fsl_ssi {
struct clk *baudclk;
unsigned int baudclk_streams;
 
-   /* regcache for volatile regs */
u32 regcache_sfcsr;
u32 regcache_sacnt;
 
-   /* DMA params */
struct snd_dmaengine_dai_dma_data dma_params_tx;
struct snd_dmaengine_dai_dma_data dma_params_rx;
dma_addr_t ssi_phys;
 
-   /* params for non-dma FIQ stream filtered mode */
struct imx_pcm_fiq_params fiq_params;
 
-   /* Used when using fsl-ssi as sound-card. This is only used by ppc and
-* should be replaced with simple-sound-card. */
struct platform_device *pdev;
 
struct fsl_ssi_dbg dbg_stats;
@@ -271,19 +272,19 @@ struct fsl_ssi {
 };
 
 /*
- * imx51 

[PATCH v2 03/11] ASoC: fsl_ssi: Refine all comments

2017-12-12 Thread Nicolin Chen
This patch refines the comments by:
1) Removing all out-of-date comments
2) Removing all not-so-useful comments
3) Unifying the styles of all comments
4) Simplifying over-descriptive comments
5) Adding comments to improve code readablity
6) Moving all register related comments to fsl_ssi.h
7) Adding comments to all register and field defines

Signed-off-by: Nicolin Chen 
---

Changelog
v1->v2
 * Added some new comments at "SoC specific data" to be more precise.
 * Revised one comment in fsl_ssi_config().
 * Revised the comment of fsl_ssi_setup_reg_vals().
 * Added one comment for AC97 in fsl_ssi_setup_reg_vals().
 * Revised the comment of fsl_ssi_hw_params() to be more precise.
 * Added some comments in _fsl_ssi_set_dai_fmt() to help understand the formats.
 * Added one comment in fsl_ssi_set_dai_fmt() to state why AC97 needs to bypass 
it.
 * Revised comments in fsl_ssi_set_dai_tdm_slot() to be more precise.
 * Revised comments around dual FIFO code in fsl_ssi_imx_probe() to be more 
precise.

 sound/soc/fsl/fsl_ssi.c | 376 ++--
 sound/soc/fsl/fsl_ssi.h |  67 +++-
 sound/soc/fsl/fsl_ssi_dbg.c |  12 +-
 3 files changed, 188 insertions(+), 267 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e903c92..796a7ea 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -187,42 +187,48 @@ struct fsl_ssi_soc_data {
 /**
  * fsl_ssi: per-SSI private data
  *
- * @reg: Pointer to the regmap registers
+ * @regs: Pointer to the regmap registers
  * @irq: IRQ of this SSI
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
- * @i2s_mode: i2s and network mode configuration of the device. Is used to
- * switch between normal and i2s/network mode
- * mode depending on the number of channels
+ * @i2s_mode: I2S and Network mode configuration of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
- * @use_dual_fifo: DMA with support for both FIFOs used
- * @fifo_deph: Depth of the SSI FIFOs
- * @slot_width: width of each DAI slot
- * @slots: number of slots
- * @rxtx_reg_val: Specific register settings for receive/transmit configuration
+ * @use_dual_fifo: DMA with support for dual FIFO mode
+ * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
+ * @fifo_depth: Depth of the SSI FIFOs
+ * @slot_width: Width of each DAI slot
+ * @slots: Number of slots
+ * @rxtx_reg_val: Specific RX/TX register settings
  *
- * @clk: SSI clock
- * @baudclk: SSI baud clock for master mode
+ * @clk: Clock source to access register
+ * @baudclk: Clock source to generate bit and frame-sync clocks
  * @baudclk_streams: Active streams that are using baudclk
  *
+ * @regcache_sfcsr: Cache sfcsr register value during suspend and resume
+ * @regcache_sacnt: Cache sacnt register value during suspend and resume
+ *
  * @dma_params_tx: DMA transmit parameters
  * @dma_params_rx: DMA receive parameters
  * @ssi_phys: physical address of the SSI registers
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev used for deprecated fsl-ssi sound card
+ * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
+ *TODO: Should be replaced with simple-sound-card
  *
  * @dbg_stats: Debugging statistics
  *
  * @soc: SoC specific data
+ * @dev: Pointer to >dev
+ *
+ * @fifo_watermark: The FIFO watermark setting. Notifies DMA when there are
+ *  @fifo_watermark or fewer words in TX fifo or
+ *  @fifo_watermark or more empty words in RX fifo.
+ * @dma_maxburst: Max number of words to transfer in one go. So far,
+ *this is always the same as fifo_watermark.
  *
- * @fifo_watermark: the FIFO watermark setting.  Notifies DMA when
- * there are @fifo_watermark or fewer words in TX fifo or
- * @fifo_watermark or more empty words in RX fifo.
- * @dma_maxburst: max number of words to transfer in one go.  So far,
- * this is always the same as fifo_watermark.
+ * @ac97_reg_lock: Mutex lock to serialize AC97 register access operations
  */
 struct fsl_ssi {
struct regmap *regs;
@@ -243,20 +249,15 @@ struct fsl_ssi {
struct clk *baudclk;
unsigned int baudclk_streams;
 
-   /* regcache for volatile regs */
u32 regcache_sfcsr;
u32 regcache_sacnt;
 
-   /* DMA params */
struct snd_dmaengine_dai_dma_data dma_params_tx;
struct snd_dmaengine_dai_dma_data dma_params_rx;
dma_addr_t ssi_phys;
 
-   /* params for non-dma FIQ stream filtered mode */
struct imx_pcm_fiq_params fiq_params;
 
-   /* Used when using fsl-ssi as sound-card. This is only used by ppc and
-* should be replaced with simple-sound-card. */
struct platform_device *pdev;
 
struct fsl_ssi_dbg dbg_stats;
@@ -271,19 +272,19 @@ struct fsl_ssi {
 };
 
 /*
- * imx51 and later SoCs have a 

[PATCH v2 10/11] ASoC: fsl_ssi: Rename i2smode to i2s_net

2017-12-12 Thread Nicolin Chen
Since this i2smode also includes the setting of Network mode, it
should have it in the name. This patch also adds its MASK define.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 24 
 sound/soc/fsl/fsl_ssi.h |  1 +
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7a8a768..dd091eb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -201,7 +201,7 @@ struct fsl_ssi_soc_data {
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
- * @i2s_mode: I2S and Network mode configuration of SCR register
+ * @i2s_net: I2S and Network mode configurations of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
  * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
@@ -245,7 +245,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
-   u8 i2s_mode;
+   u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -816,16 +816,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   u8 i2smode;
+   u8 i2s_net;
/* Normal + Network mode to send 16-bit data in 32-bit frames */
if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16)
-   i2smode = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
else
-   i2smode = ssi->i2s_mode;
+   i2s_net = ssi->i2s_net;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_NET | SSI_SCR_I2S_MODE_MASK,
-  channels == 1 ? 0 : i2smode);
+  SSI_SCR_I2S_NET_MASK,
+  channels == 1 ? 0 : i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
@@ -882,7 +882,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
srcr &= ~mask;
 
/* Use Network mode as default */
-   ssi->i2s_mode = SSI_SCR_NET;
+   ssi->i2s_net = SSI_SCR_NET;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
regmap_update_bits(regs, REG_SSI_STCCR,
@@ -892,10 +892,10 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
-   ssi->i2s_mode |= SSI_SCR_I2S_MODE_MASTER;
+   ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
-   ssi->i2s_mode |= SSI_SCR_I2S_MODE_SLAVE;
+   ssi->i2s_net |= SSI_SCR_I2S_MODE_SLAVE;
break;
default:
return -EINVAL;
@@ -920,12 +920,12 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of bclk, frame high, 1clk before data */
-   ssi->i2s_mode |= SSI_SCR_I2S_MODE_NORMAL;
+   ssi->i2s_net |= SSI_SCR_I2S_MODE_NORMAL;
break;
default:
return -EINVAL;
}
-   scr |= ssi->i2s_mode;
+   scr |= ssi->i2s_net;
 
/* DAI clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index 52b88f1..b610087 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -95,6 +95,7 @@
 #define SSI_SCR_I2S_MODE_SLAVE 0x0040
 #define SSI_SCR_SYN0x0010
 #define SSI_SCR_NET0x0008
+#define SSI_SCR_I2S_NET_MASK   (SSI_SCR_NET | SSI_SCR_I2S_MODE_MASK)
 #define SSI_SCR_RE 0x0004
 #define SSI_SCR_TE 0x0002
 #define SSI_SCR_SSIEN  0x0001
-- 
2.7.4



[PATCH v2 04/11] ASoC: fsl_ssi: Rename registers and fields macros

2017-12-12 Thread Nicolin Chen
This patch renames CCSR_SSI_xxx to REG_SSI_xxx and SSI_xxx_yyy style.
It also slightly reduces the length of them to save some space.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 374 +--
 sound/soc/fsl/fsl_ssi.h | 376 ++--
 sound/soc/fsl/fsl_ssi_dbg.c |  44 +++---
 3 files changed, 397 insertions(+), 397 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 796a7ea..8b5407d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -78,12 +78,12 @@
 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
-#define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \
-   CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \
-   CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN)
-#define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \
-   CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \
-   CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN)
+#define FSLSSI_SIER_DBG_RX_FLAGS (SSI_SIER_RFF0_EN | \
+   SSI_SIER_RLS_EN | SSI_SIER_RFS_EN | \
+   SSI_SIER_ROE0_EN | SSI_SIER_RFRC_EN)
+#define FSLSSI_SIER_DBG_TX_FLAGS (SSI_SIER_TFE0_EN | \
+   SSI_SIER_TLS_EN | SSI_SIER_TFS_EN | \
+   SSI_SIER_TUE0_EN | SSI_SIER_TFRC_EN)
 
 enum fsl_ssi_type {
FSL_SSI_MCP8610,
@@ -107,8 +107,8 @@ struct fsl_ssi_rxtx_reg_val {
 static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_SACCEN:
-   case CCSR_SSI_SACCDIS:
+   case REG_SSI_SACCEN:
+   case REG_SSI_SACCDIS:
return false;
default:
return true;
@@ -118,18 +118,18 @@ static bool fsl_ssi_readable_reg(struct device *dev, 
unsigned int reg)
 static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_STX0:
-   case CCSR_SSI_STX1:
-   case CCSR_SSI_SRX0:
-   case CCSR_SSI_SRX1:
-   case CCSR_SSI_SISR:
-   case CCSR_SSI_SFCSR:
-   case CCSR_SSI_SACNT:
-   case CCSR_SSI_SACADD:
-   case CCSR_SSI_SACDAT:
-   case CCSR_SSI_SATAG:
-   case CCSR_SSI_SACCST:
-   case CCSR_SSI_SOR:
+   case REG_SSI_STX0:
+   case REG_SSI_STX1:
+   case REG_SSI_SRX0:
+   case REG_SSI_SRX1:
+   case REG_SSI_SISR:
+   case REG_SSI_SFCSR:
+   case REG_SSI_SACNT:
+   case REG_SSI_SACADD:
+   case REG_SSI_SACDAT:
+   case REG_SSI_SATAG:
+   case REG_SSI_SACCST:
+   case REG_SSI_SOR:
return true;
default:
return false;
@@ -139,12 +139,12 @@ static bool fsl_ssi_volatile_reg(struct device *dev, 
unsigned int reg)
 static bool fsl_ssi_precious_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_SRX0:
-   case CCSR_SSI_SRX1:
-   case CCSR_SSI_SISR:
-   case CCSR_SSI_SACADD:
-   case CCSR_SSI_SACDAT:
-   case CCSR_SSI_SATAG:
+   case REG_SSI_SRX0:
+   case REG_SSI_SRX1:
+   case REG_SSI_SISR:
+   case REG_SSI_SACADD:
+   case REG_SSI_SACDAT:
+   case REG_SSI_SATAG:
return true;
default:
return false;
@@ -154,9 +154,9 @@ static bool fsl_ssi_precious_reg(struct device *dev, 
unsigned int reg)
 static bool fsl_ssi_writeable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_SRX0:
-   case CCSR_SSI_SRX1:
-   case CCSR_SSI_SACCST:
+   case REG_SSI_SRX0:
+   case REG_SSI_SRX1:
+   case REG_SSI_SACCST:
return false;
default:
return true;
@@ -164,12 +164,12 @@ static bool fsl_ssi_writeable_reg(struct device *dev, 
unsigned int reg)
 }
 
 static const struct regmap_config fsl_ssi_regconfig = {
-   .max_register = CCSR_SSI_SACCDIS,
+   .max_register = REG_SSI_SACCDIS,
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.val_format_endian = REGMAP_ENDIAN_NATIVE,
-   .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1,
+   .num_reg_defaults_raw = REG_SSI_SACCDIS / sizeof(uint32_t) + 1,
.readable_reg = fsl_ssi_readable_reg,
.volatile_reg = fsl_ssi_volatile_reg,
.precious_reg = fsl_ssi_precious_reg,
@@ -290,9 +290,9 @@ struct fsl_ssi {
 static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
.imx = false,
.offline_config = true,
-   .sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
-   CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
-   CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
+   .sisr_write_mask = SSI_SISR_RFRC | SSI_SISR_TFRC |
+   SSI_SISR_ROE0 | SSI_SISR_ROE1 |
+   SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
@@ 

[PATCH v2 10/11] ASoC: fsl_ssi: Rename i2smode to i2s_net

2017-12-12 Thread Nicolin Chen
Since this i2smode also includes the setting of Network mode, it
should have it in the name. This patch also adds its MASK define.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 24 
 sound/soc/fsl/fsl_ssi.h |  1 +
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7a8a768..dd091eb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -201,7 +201,7 @@ struct fsl_ssi_soc_data {
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
- * @i2s_mode: I2S and Network mode configuration of SCR register
+ * @i2s_net: I2S and Network mode configurations of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
  * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
@@ -245,7 +245,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
-   u8 i2s_mode;
+   u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -816,16 +816,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   u8 i2smode;
+   u8 i2s_net;
/* Normal + Network mode to send 16-bit data in 32-bit frames */
if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16)
-   i2smode = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
else
-   i2smode = ssi->i2s_mode;
+   i2s_net = ssi->i2s_net;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_NET | SSI_SCR_I2S_MODE_MASK,
-  channels == 1 ? 0 : i2smode);
+  SSI_SCR_I2S_NET_MASK,
+  channels == 1 ? 0 : i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
@@ -882,7 +882,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
srcr &= ~mask;
 
/* Use Network mode as default */
-   ssi->i2s_mode = SSI_SCR_NET;
+   ssi->i2s_net = SSI_SCR_NET;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
regmap_update_bits(regs, REG_SSI_STCCR,
@@ -892,10 +892,10 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
-   ssi->i2s_mode |= SSI_SCR_I2S_MODE_MASTER;
+   ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
-   ssi->i2s_mode |= SSI_SCR_I2S_MODE_SLAVE;
+   ssi->i2s_net |= SSI_SCR_I2S_MODE_SLAVE;
break;
default:
return -EINVAL;
@@ -920,12 +920,12 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of bclk, frame high, 1clk before data */
-   ssi->i2s_mode |= SSI_SCR_I2S_MODE_NORMAL;
+   ssi->i2s_net |= SSI_SCR_I2S_MODE_NORMAL;
break;
default:
return -EINVAL;
}
-   scr |= ssi->i2s_mode;
+   scr |= ssi->i2s_net;
 
/* DAI clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index 52b88f1..b610087 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -95,6 +95,7 @@
 #define SSI_SCR_I2S_MODE_SLAVE 0x0040
 #define SSI_SCR_SYN0x0010
 #define SSI_SCR_NET0x0008
+#define SSI_SCR_I2S_NET_MASK   (SSI_SCR_NET | SSI_SCR_I2S_MODE_MASK)
 #define SSI_SCR_RE 0x0004
 #define SSI_SCR_TE 0x0002
 #define SSI_SCR_SSIEN  0x0001
-- 
2.7.4



[PATCH v2 04/11] ASoC: fsl_ssi: Rename registers and fields macros

2017-12-12 Thread Nicolin Chen
This patch renames CCSR_SSI_xxx to REG_SSI_xxx and SSI_xxx_yyy style.
It also slightly reduces the length of them to save some space.

Signed-off-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_ssi.c | 374 +--
 sound/soc/fsl/fsl_ssi.h | 376 ++--
 sound/soc/fsl/fsl_ssi_dbg.c |  44 +++---
 3 files changed, 397 insertions(+), 397 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 796a7ea..8b5407d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -78,12 +78,12 @@
 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
-#define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \
-   CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \
-   CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN)
-#define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \
-   CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \
-   CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN)
+#define FSLSSI_SIER_DBG_RX_FLAGS (SSI_SIER_RFF0_EN | \
+   SSI_SIER_RLS_EN | SSI_SIER_RFS_EN | \
+   SSI_SIER_ROE0_EN | SSI_SIER_RFRC_EN)
+#define FSLSSI_SIER_DBG_TX_FLAGS (SSI_SIER_TFE0_EN | \
+   SSI_SIER_TLS_EN | SSI_SIER_TFS_EN | \
+   SSI_SIER_TUE0_EN | SSI_SIER_TFRC_EN)
 
 enum fsl_ssi_type {
FSL_SSI_MCP8610,
@@ -107,8 +107,8 @@ struct fsl_ssi_rxtx_reg_val {
 static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_SACCEN:
-   case CCSR_SSI_SACCDIS:
+   case REG_SSI_SACCEN:
+   case REG_SSI_SACCDIS:
return false;
default:
return true;
@@ -118,18 +118,18 @@ static bool fsl_ssi_readable_reg(struct device *dev, 
unsigned int reg)
 static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_STX0:
-   case CCSR_SSI_STX1:
-   case CCSR_SSI_SRX0:
-   case CCSR_SSI_SRX1:
-   case CCSR_SSI_SISR:
-   case CCSR_SSI_SFCSR:
-   case CCSR_SSI_SACNT:
-   case CCSR_SSI_SACADD:
-   case CCSR_SSI_SACDAT:
-   case CCSR_SSI_SATAG:
-   case CCSR_SSI_SACCST:
-   case CCSR_SSI_SOR:
+   case REG_SSI_STX0:
+   case REG_SSI_STX1:
+   case REG_SSI_SRX0:
+   case REG_SSI_SRX1:
+   case REG_SSI_SISR:
+   case REG_SSI_SFCSR:
+   case REG_SSI_SACNT:
+   case REG_SSI_SACADD:
+   case REG_SSI_SACDAT:
+   case REG_SSI_SATAG:
+   case REG_SSI_SACCST:
+   case REG_SSI_SOR:
return true;
default:
return false;
@@ -139,12 +139,12 @@ static bool fsl_ssi_volatile_reg(struct device *dev, 
unsigned int reg)
 static bool fsl_ssi_precious_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_SRX0:
-   case CCSR_SSI_SRX1:
-   case CCSR_SSI_SISR:
-   case CCSR_SSI_SACADD:
-   case CCSR_SSI_SACDAT:
-   case CCSR_SSI_SATAG:
+   case REG_SSI_SRX0:
+   case REG_SSI_SRX1:
+   case REG_SSI_SISR:
+   case REG_SSI_SACADD:
+   case REG_SSI_SACDAT:
+   case REG_SSI_SATAG:
return true;
default:
return false;
@@ -154,9 +154,9 @@ static bool fsl_ssi_precious_reg(struct device *dev, 
unsigned int reg)
 static bool fsl_ssi_writeable_reg(struct device *dev, unsigned int reg)
 {
switch (reg) {
-   case CCSR_SSI_SRX0:
-   case CCSR_SSI_SRX1:
-   case CCSR_SSI_SACCST:
+   case REG_SSI_SRX0:
+   case REG_SSI_SRX1:
+   case REG_SSI_SACCST:
return false;
default:
return true;
@@ -164,12 +164,12 @@ static bool fsl_ssi_writeable_reg(struct device *dev, 
unsigned int reg)
 }
 
 static const struct regmap_config fsl_ssi_regconfig = {
-   .max_register = CCSR_SSI_SACCDIS,
+   .max_register = REG_SSI_SACCDIS,
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.val_format_endian = REGMAP_ENDIAN_NATIVE,
-   .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1,
+   .num_reg_defaults_raw = REG_SSI_SACCDIS / sizeof(uint32_t) + 1,
.readable_reg = fsl_ssi_readable_reg,
.volatile_reg = fsl_ssi_volatile_reg,
.precious_reg = fsl_ssi_precious_reg,
@@ -290,9 +290,9 @@ struct fsl_ssi {
 static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
.imx = false,
.offline_config = true,
-   .sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
-   CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
-   CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
+   .sisr_write_mask = SSI_SISR_RFRC | SSI_SISR_TFRC |
+   SSI_SISR_ROE0 | SSI_SISR_ROE1 |
+   SSI_SISR_TUE0 | SSI_SISR_TUE1,
 };
 
 static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
@@ -305,16 +305,16 @@ static 

[PATCH v2 00/11] ASoC: fsl_ssi: Clean up - coding style level

2017-12-12 Thread Nicolin Chen
==Changelog==
v1->v2
 * Dropped one patch to remove "struct device"
 * Revised PATCH-03 "Refine all comments"
 * Revised PATCH-05 "Refine indentations and wrappings"
 * Rebased all other patches
 * Added PATCH-10 "Rename i2smode to i2s_net"
 * Added PATCH-11 "Define ternary macros to simplify code"

 # Detialed changes are described in each updated patch.

==Background==
The fsl_ssi driver was designed for PPC originally and then it has
been updated to support different modes for i.MX Series, including
SDMA, I2S Master mode, AC97 and older i.MXs with FIQ, by different
contributors for different use cases in different coding styles.

Additionally, in order to fix/work-around hardware bugs and design
flaws, the driver made a lot of compromise so now its program flow
looks very complicated and it's getting hard to maintain or update.

So I am going to clean up the driver on both coding style level and
program flow level.

==Introduction==
This series of patches is the first set to clean up fsl_ssi driver
in the coding style level. Any patch here is not supposed to change
the program flow.

==Verification==
Theoretically, since these patches do not change program flow, they
only need code review, build or sanity tests. I have done build and
sanity tests on an i.MX6SoloX with WM8962 using imx_v6_v7_defconfig
and playback/record tests in I2S Master/Slave modes.

Nicolin Chen (11):
  ASoC: fsl_ssi: Rename fsl_ssi_private to fsl_ssi
  ASoC: fsl_ssi: Cache pdev->dev pointer
  ASoC: fsl_ssi: Refine all comments
  ASoC: fsl_ssi: Rename registers and fields macros
  ASoC: fsl_ssi: Refine indentations and wrappings
  ASoC: fsl_ssi: Refine printk outputs
  ASoC: fsl_ssi: Rename cpu_dai parameter to dai
  ASoC: fsl_ssi: Rename scr_val to scr
  ASoC: fsl_ssi: Replace fsl_ssi_rxtx_reg_val with fsl_ssi_regvals
  ASoC: fsl_ssi: Rename i2smode to i2s_net
  ASoC: fsl_ssi: Define ternary macros to simplify code

 sound/soc/fsl/fsl_ssi.c | 1373 +++
 sound/soc/fsl/fsl_ssi.h |  427 --
 sound/soc/fsl/fsl_ssi_dbg.c |   59 +-
 3 files changed, 876 insertions(+), 983 deletions(-)

-- 
2.7.4



[PATCH v2 00/11] ASoC: fsl_ssi: Clean up - coding style level

2017-12-12 Thread Nicolin Chen
==Changelog==
v1->v2
 * Dropped one patch to remove "struct device"
 * Revised PATCH-03 "Refine all comments"
 * Revised PATCH-05 "Refine indentations and wrappings"
 * Rebased all other patches
 * Added PATCH-10 "Rename i2smode to i2s_net"
 * Added PATCH-11 "Define ternary macros to simplify code"

 # Detialed changes are described in each updated patch.

==Background==
The fsl_ssi driver was designed for PPC originally and then it has
been updated to support different modes for i.MX Series, including
SDMA, I2S Master mode, AC97 and older i.MXs with FIQ, by different
contributors for different use cases in different coding styles.

Additionally, in order to fix/work-around hardware bugs and design
flaws, the driver made a lot of compromise so now its program flow
looks very complicated and it's getting hard to maintain or update.

So I am going to clean up the driver on both coding style level and
program flow level.

==Introduction==
This series of patches is the first set to clean up fsl_ssi driver
in the coding style level. Any patch here is not supposed to change
the program flow.

==Verification==
Theoretically, since these patches do not change program flow, they
only need code review, build or sanity tests. I have done build and
sanity tests on an i.MX6SoloX with WM8962 using imx_v6_v7_defconfig
and playback/record tests in I2S Master/Slave modes.

Nicolin Chen (11):
  ASoC: fsl_ssi: Rename fsl_ssi_private to fsl_ssi
  ASoC: fsl_ssi: Cache pdev->dev pointer
  ASoC: fsl_ssi: Refine all comments
  ASoC: fsl_ssi: Rename registers and fields macros
  ASoC: fsl_ssi: Refine indentations and wrappings
  ASoC: fsl_ssi: Refine printk outputs
  ASoC: fsl_ssi: Rename cpu_dai parameter to dai
  ASoC: fsl_ssi: Rename scr_val to scr
  ASoC: fsl_ssi: Replace fsl_ssi_rxtx_reg_val with fsl_ssi_regvals
  ASoC: fsl_ssi: Rename i2smode to i2s_net
  ASoC: fsl_ssi: Define ternary macros to simplify code

 sound/soc/fsl/fsl_ssi.c | 1373 +++
 sound/soc/fsl/fsl_ssi.h |  427 --
 sound/soc/fsl/fsl_ssi_dbg.c |   59 +-
 3 files changed, 876 insertions(+), 983 deletions(-)

-- 
2.7.4



[PATCH 4/5] phy: renesas: rcar-gen3-usb2: add rcar_gen3_role_swap_ops

2017-12-12 Thread Yoshihiro Shimoda
This patch add rcar_gen3_role_swap_ops to support other feature
(e.g. gpio handling) easily.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 51 +++-
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 6d6f3eb..5e509a9 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -83,11 +83,23 @@
 
 #define RCAR_GEN3_PHY_HAS_DEDICATED_PINS   1
 
+struct rcar_gen3_chan;
+struct rcar_gen3_role_swap_ops {
+   void (*init)(struct rcar_gen3_chan *ch);
+   void (*set_host)(struct rcar_gen3_chan *ch, int host);
+   bool (*is_host)(struct rcar_gen3_chan *ch);
+   void (*enable_vbus)(struct rcar_gen3_chan *ch, int vbus);
+   bool (*check_id)(struct rcar_gen3_chan *ch);
+   void (*enable_irq)(struct rcar_gen3_chan *ch, int enable);
+   irqreturn_t (*irq_handler)(struct rcar_gen3_chan *ch);
+};
+
 struct rcar_gen3_chan {
void __iomem *base;
struct extcon_dev *extcon;
struct phy *phy;
struct regulator *vbus;
+   const struct rcar_gen3_role_swap_ops *rs_ops;
struct work_struct work;
bool extcon_host;
bool has_otg_pins;
@@ -203,17 +215,20 @@ static void rcar_gen3_phy_usb2_work(struct work_struct 
*work)
 
 static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
 {
-   has_otg_pins_set_host(ch, host);
+   if (ch->rs_ops && ch->rs_ops->set_host)
+   ch->rs_ops->set_host(ch, host);
 }
 
 static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
 {
-   has_otg_pins_enable_vbus(ch, vbus);
+   if (ch->rs_ops && ch->rs_ops->enable_vbus)
+   ch->rs_ops->enable_vbus(ch, vbus);
 }
 
 static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable)
 {
-   has_otg_pins_enable_irq(ch, enable);
+   if (ch->rs_ops && ch->rs_ops->enable_irq)
+   ch->rs_ops->enable_irq(ch, enable);
 }
 
 static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
@@ -271,7 +286,10 @@ static void rcar_gen3_init_from_a_peri_to_a_host(struct 
rcar_gen3_chan *ch)
 
 static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
 {
-   return has_otg_pins_check_id(ch);
+   if (ch->rs_ops && ch->rs_ops->check_id)
+   return ch->rs_ops->check_id(ch);
+
+   return false;
 }
 
 static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
@@ -284,7 +302,10 @@ static void rcar_gen3_device_recognition(struct 
rcar_gen3_chan *ch)
 
 static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch)
 {
-   return has_otg_pins_is_host(ch);
+   if (ch->rs_ops && ch->rs_ops->is_host)
+   return ch->rs_ops->is_host(ch);
+
+   return false;
 }
 
 static enum phy_mode rcar_gen3_get_phy_mode(struct rcar_gen3_chan *ch)
@@ -350,7 +371,8 @@ static ssize_t role_show(struct device *dev, struct 
device_attribute *attr,
 
 static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
 {
-   has_otg_pins_init(ch);
+   if (ch->rs_ops && ch->rs_ops->init)
+   ch->rs_ops->init(ch);
 
rcar_gen3_device_recognition(ch);
 }
@@ -425,9 +447,10 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
 static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
 {
struct rcar_gen3_chan *ch = _ch;
-   irqreturn_t ret;
+   irqreturn_t ret = IRQ_NONE;
 
-   ret = has_otg_pins_irq_handler(ch);
+   if (ch->rs_ops && ch->rs_ops->irq_handler)
+   ret = ch->rs_ops->irq_handler(ch);
if (ret == IRQ_HANDLED)
rcar_gen3_device_recognition(ch);
 
@@ -456,6 +479,16 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void 
*_ch)
EXTCON_NONE,
 };
 
+static const struct rcar_gen3_role_swap_ops has_otg_pins_ops = {
+   .init   = has_otg_pins_init,
+   .set_host   = has_otg_pins_set_host,
+   .is_host= has_otg_pins_is_host,
+   .enable_vbus= has_otg_pins_enable_vbus,
+   .check_id   = has_otg_pins_check_id,
+   .enable_irq = has_otg_pins_enable_irq,
+   .irq_handler= has_otg_pins_irq_handler,
+};
+
 static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -493,6 +526,8 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device 
*pdev)
int ret;
 
channel->has_otg_pins = 
(uintptr_t)of_device_get_match_data(dev);
+   if (channel->has_otg_pins)
+   channel->rs_ops = _otg_pins_ops;
channel->extcon = devm_extcon_dev_allocate(dev,
rcar_gen3_phy_cable);
if (IS_ERR(channel->extcon))
-- 
1.9.1



[PATCH 4/5] phy: renesas: rcar-gen3-usb2: add rcar_gen3_role_swap_ops

2017-12-12 Thread Yoshihiro Shimoda
This patch add rcar_gen3_role_swap_ops to support other feature
(e.g. gpio handling) easily.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 51 +++-
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 6d6f3eb..5e509a9 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -83,11 +83,23 @@
 
 #define RCAR_GEN3_PHY_HAS_DEDICATED_PINS   1
 
+struct rcar_gen3_chan;
+struct rcar_gen3_role_swap_ops {
+   void (*init)(struct rcar_gen3_chan *ch);
+   void (*set_host)(struct rcar_gen3_chan *ch, int host);
+   bool (*is_host)(struct rcar_gen3_chan *ch);
+   void (*enable_vbus)(struct rcar_gen3_chan *ch, int vbus);
+   bool (*check_id)(struct rcar_gen3_chan *ch);
+   void (*enable_irq)(struct rcar_gen3_chan *ch, int enable);
+   irqreturn_t (*irq_handler)(struct rcar_gen3_chan *ch);
+};
+
 struct rcar_gen3_chan {
void __iomem *base;
struct extcon_dev *extcon;
struct phy *phy;
struct regulator *vbus;
+   const struct rcar_gen3_role_swap_ops *rs_ops;
struct work_struct work;
bool extcon_host;
bool has_otg_pins;
@@ -203,17 +215,20 @@ static void rcar_gen3_phy_usb2_work(struct work_struct 
*work)
 
 static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
 {
-   has_otg_pins_set_host(ch, host);
+   if (ch->rs_ops && ch->rs_ops->set_host)
+   ch->rs_ops->set_host(ch, host);
 }
 
 static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
 {
-   has_otg_pins_enable_vbus(ch, vbus);
+   if (ch->rs_ops && ch->rs_ops->enable_vbus)
+   ch->rs_ops->enable_vbus(ch, vbus);
 }
 
 static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable)
 {
-   has_otg_pins_enable_irq(ch, enable);
+   if (ch->rs_ops && ch->rs_ops->enable_irq)
+   ch->rs_ops->enable_irq(ch, enable);
 }
 
 static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
@@ -271,7 +286,10 @@ static void rcar_gen3_init_from_a_peri_to_a_host(struct 
rcar_gen3_chan *ch)
 
 static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
 {
-   return has_otg_pins_check_id(ch);
+   if (ch->rs_ops && ch->rs_ops->check_id)
+   return ch->rs_ops->check_id(ch);
+
+   return false;
 }
 
 static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
@@ -284,7 +302,10 @@ static void rcar_gen3_device_recognition(struct 
rcar_gen3_chan *ch)
 
 static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch)
 {
-   return has_otg_pins_is_host(ch);
+   if (ch->rs_ops && ch->rs_ops->is_host)
+   return ch->rs_ops->is_host(ch);
+
+   return false;
 }
 
 static enum phy_mode rcar_gen3_get_phy_mode(struct rcar_gen3_chan *ch)
@@ -350,7 +371,8 @@ static ssize_t role_show(struct device *dev, struct 
device_attribute *attr,
 
 static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
 {
-   has_otg_pins_init(ch);
+   if (ch->rs_ops && ch->rs_ops->init)
+   ch->rs_ops->init(ch);
 
rcar_gen3_device_recognition(ch);
 }
@@ -425,9 +447,10 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
 static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
 {
struct rcar_gen3_chan *ch = _ch;
-   irqreturn_t ret;
+   irqreturn_t ret = IRQ_NONE;
 
-   ret = has_otg_pins_irq_handler(ch);
+   if (ch->rs_ops && ch->rs_ops->irq_handler)
+   ret = ch->rs_ops->irq_handler(ch);
if (ret == IRQ_HANDLED)
rcar_gen3_device_recognition(ch);
 
@@ -456,6 +479,16 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void 
*_ch)
EXTCON_NONE,
 };
 
+static const struct rcar_gen3_role_swap_ops has_otg_pins_ops = {
+   .init   = has_otg_pins_init,
+   .set_host   = has_otg_pins_set_host,
+   .is_host= has_otg_pins_is_host,
+   .enable_vbus= has_otg_pins_enable_vbus,
+   .check_id   = has_otg_pins_check_id,
+   .enable_irq = has_otg_pins_enable_irq,
+   .irq_handler= has_otg_pins_irq_handler,
+};
+
 static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -493,6 +526,8 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device 
*pdev)
int ret;
 
channel->has_otg_pins = 
(uintptr_t)of_device_get_match_data(dev);
+   if (channel->has_otg_pins)
+   channel->rs_ops = _otg_pins_ops;
channel->extcon = devm_extcon_dev_allocate(dev,
rcar_gen3_phy_cable);
if (IS_ERR(channel->extcon))
-- 
1.9.1



[PATCH 0/5] phy: renesas: rcar-gen3-usb2: add gpio handling for R-Car D3

2017-12-12 Thread Yoshihiro Shimoda
This patch set is based on the latest linux-phy / next branch
(commit id = 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323).

This new feature will be used by the renesas_usbhs driver on R-Car D3.

Yoshihiro Shimoda (5):
  phy: renesas: rcar-gen3-usb2: call INIT_WORK() anyway
  phy: renesas: rcar-gen3-usb2: unify OBINTEN handling
  phy: renesas: rcar-gen3-usb2: use prefix "has_otg_pins_" for dedicated
pins handling
  phy: renesas: rcar-gen3-usb2: add rcar_gen3_role_swap_ops
  phy: renesas: rcar-gen3-usb2: add gpio handlings

 .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt |   2 +
 drivers/phy/renesas/phy-rcar-gen3-usb2.c   | 262 -
 2 files changed, 206 insertions(+), 58 deletions(-)

-- 
1.9.1



[PATCH 0/5] phy: renesas: rcar-gen3-usb2: add gpio handling for R-Car D3

2017-12-12 Thread Yoshihiro Shimoda
This patch set is based on the latest linux-phy / next branch
(commit id = 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323).

This new feature will be used by the renesas_usbhs driver on R-Car D3.

Yoshihiro Shimoda (5):
  phy: renesas: rcar-gen3-usb2: call INIT_WORK() anyway
  phy: renesas: rcar-gen3-usb2: unify OBINTEN handling
  phy: renesas: rcar-gen3-usb2: use prefix "has_otg_pins_" for dedicated
pins handling
  phy: renesas: rcar-gen3-usb2: add rcar_gen3_role_swap_ops
  phy: renesas: rcar-gen3-usb2: add gpio handlings

 .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt |   2 +
 drivers/phy/renesas/phy-rcar-gen3-usb2.c   | 262 -
 2 files changed, 206 insertions(+), 58 deletions(-)

-- 
1.9.1



[PATCH 2/5] phy: renesas: rcar-gen3-usb2: unify OBINTEN handling

2017-12-12 Thread Yoshihiro Shimoda
This patch unifies the OBINTEN handling to clean-up the code.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index c22d65a..beeaa30 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -147,6 +147,18 @@ static void rcar_gen3_enable_vbus_ctrl(struct 
rcar_gen3_chan *ch, int vbus)
writel(val, usb2_base + USB2_ADPCTRL);
 }
 
+static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable)
+{
+   void __iomem *usb2_base = ch->base;
+   u32 val = readl(usb2_base + USB2_OBINTEN);
+
+   if (enable)
+   val |= USB2_OBINT_BITS;
+   else
+   val &= ~USB2_OBINT_BITS;
+   writel(val, usb2_base + USB2_OBINTEN);
+}
+
 static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
 {
rcar_gen3_set_linectrl(ch, 1, 1);
@@ -192,16 +204,12 @@ static void rcar_gen3_init_for_a_peri(struct 
rcar_gen3_chan *ch)
 
 static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
 {
-   void __iomem *usb2_base = ch->base;
-   u32 val;
-
-   val = readl(usb2_base + USB2_OBINTEN);
-   writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+   rcar_gen3_enable_otg_irq(ch, 0);
 
rcar_gen3_enable_vbus_ctrl(ch, 0);
rcar_gen3_init_for_host(ch);
 
-   writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+   rcar_gen3_enable_otg_irq(ch, 1);
 }
 
 static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
@@ -291,8 +299,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
val = readl(usb2_base + USB2_VBCTRL);
writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
-   val = readl(usb2_base + USB2_OBINTEN);
-   writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+   rcar_gen3_enable_otg_irq(ch, 1);
val = readl(usb2_base + USB2_ADPCTRL);
writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
val = readl(usb2_base + USB2_LINECTRL1);
-- 
1.9.1



[PATCH 2/5] phy: renesas: rcar-gen3-usb2: unify OBINTEN handling

2017-12-12 Thread Yoshihiro Shimoda
This patch unifies the OBINTEN handling to clean-up the code.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index c22d65a..beeaa30 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -147,6 +147,18 @@ static void rcar_gen3_enable_vbus_ctrl(struct 
rcar_gen3_chan *ch, int vbus)
writel(val, usb2_base + USB2_ADPCTRL);
 }
 
+static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable)
+{
+   void __iomem *usb2_base = ch->base;
+   u32 val = readl(usb2_base + USB2_OBINTEN);
+
+   if (enable)
+   val |= USB2_OBINT_BITS;
+   else
+   val &= ~USB2_OBINT_BITS;
+   writel(val, usb2_base + USB2_OBINTEN);
+}
+
 static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
 {
rcar_gen3_set_linectrl(ch, 1, 1);
@@ -192,16 +204,12 @@ static void rcar_gen3_init_for_a_peri(struct 
rcar_gen3_chan *ch)
 
 static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
 {
-   void __iomem *usb2_base = ch->base;
-   u32 val;
-
-   val = readl(usb2_base + USB2_OBINTEN);
-   writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+   rcar_gen3_enable_otg_irq(ch, 0);
 
rcar_gen3_enable_vbus_ctrl(ch, 0);
rcar_gen3_init_for_host(ch);
 
-   writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+   rcar_gen3_enable_otg_irq(ch, 1);
 }
 
 static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
@@ -291,8 +299,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
val = readl(usb2_base + USB2_VBCTRL);
writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
-   val = readl(usb2_base + USB2_OBINTEN);
-   writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+   rcar_gen3_enable_otg_irq(ch, 1);
val = readl(usb2_base + USB2_ADPCTRL);
writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
val = readl(usb2_base + USB2_LINECTRL1);
-- 
1.9.1



[PATCH 5/5] phy: renesas: rcar-gen3-usb2: add gpio handling

2017-12-12 Thread Yoshihiro Shimoda
Some R-Car SoCs (e.g. R-Car D3) doesn't have dedicated pins of VBUS
and ID. So, they may be connected to gpio pins. To handle the gpio
pins, this patch adds the handling of VBUS and ID pins instead of
dedicated pins.

Signed-off-by: Yoshihiro Shimoda 
---
 .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt |  2 +
 drivers/phy/renesas/phy-rcar-gen3-usb2.c   | 77 --
 2 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt 
b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
index 99b651b..851582f 100644
--- a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
+++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
@@ -27,6 +27,8 @@ channel as USB OTG:
 - interrupts: interrupt specifier for the PHY.
 - vbus-supply: Phandle to a regulator that provides power to the VBUS. This
   regulator will be managed during the PHY power on/off sequence.
+- renesas,vbus-gpios: use gpio to control vbus instead of dedicated pin.
+- renesas,id-gpios: use gpio to detect id instead of dedicated pin.
 
 Example (R-Car H3):
 
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 5e509a9..0b6333d 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -13,6 +13,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -100,9 +101,12 @@ struct rcar_gen3_chan {
struct phy *phy;
struct regulator *vbus;
const struct rcar_gen3_role_swap_ops *rs_ops;
+   struct gpio_desc *gpio_vbus;
+   struct gpio_desc *gpio_id;
struct work_struct work;
bool extcon_host;
bool has_otg_pins;
+   bool has_gpio;
 };
 
 static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
@@ -199,6 +203,36 @@ static void has_otg_pins_init(struct rcar_gen3_chan *ch)
   usb2_base + USB2_LINECTRL1);
 }
 
+static void gpio_enable_vbus(struct rcar_gen3_chan *ch, int vbus)
+{
+   gpiod_set_value(ch->gpio_vbus, vbus);
+}
+
+static bool gpio_check_id(struct rcar_gen3_chan *ch)
+{
+   return gpiod_get_value(ch->gpio_id);
+}
+
+static void gpio_set_host(struct rcar_gen3_chan *ch, int host)
+{
+   /* In gpio ops, this driver will modify the extcon_host by sysfs */
+   if (ch->extcon_host != !!host) {
+   ch->extcon_host = !!host;
+   schedule_work(>work);
+   }
+}
+
+static bool gpio_is_host(struct rcar_gen3_chan *ch)
+{
+   return ch->extcon_host;
+}
+
+static irqreturn_t gpio_irq_handler(struct rcar_gen3_chan *ch)
+{
+   /* Nop because the driver will get gpio value after exited */
+   return IRQ_HANDLED;
+}
+
 static void rcar_gen3_phy_usb2_work(struct work_struct *work)
 {
struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
@@ -323,7 +357,7 @@ static ssize_t role_store(struct device *dev, struct 
device_attribute *attr,
bool is_b_device;
enum phy_mode cur_mode, new_mode;
 
-   if (!ch->has_otg_pins || !ch->phy->init_count)
+   if (!(ch->has_otg_pins || ch->has_gpio) || !ch->phy->init_count)
return -EIO;
 
if (!strncmp(buf, "host", strlen("host")))
@@ -361,7 +395,7 @@ static ssize_t role_show(struct device *dev, struct 
device_attribute *attr,
 {
struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
 
-   if (!ch->has_otg_pins || !ch->phy->init_count)
+   if (!(ch->has_otg_pins || ch->has_gpio) || !ch->phy->init_count)
return -EIO;
 
return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
@@ -388,7 +422,7 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
 
/* Initialize otg part */
-   if (channel->has_otg_pins)
+   if (channel->has_otg_pins || channel->has_gpio)
rcar_gen3_init_otg(channel);
 
return 0;
@@ -489,6 +523,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void 
*_ch)
.irq_handler= has_otg_pins_irq_handler,
 };
 
+static const struct rcar_gen3_role_swap_ops gpio_ops = {
+   .set_host   = gpio_set_host,
+   .is_host= gpio_is_host,
+   .enable_vbus= gpio_enable_vbus,
+   .check_id   = gpio_check_id,
+   .irq_handler= gpio_irq_handler,
+};
+
 static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -513,9 +555,30 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device 
*pdev)
 
INIT_WORK(>work, rcar_gen3_phy_usb2_work);
 
-   /* call request_irq for OTG */
+   channel->gpio_vbus = devm_gpiod_get(dev, "renesas,vbus", GPIOD_OUT_LOW);
+   if (IS_ERR(channel->gpio_vbus) &&
+   PTR_ERR(channel->gpio_vbus) == -EPROBE_DEFER)
+   return PTR_ERR(channel->gpio_vbus);
+
+   

[PATCH 5/5] phy: renesas: rcar-gen3-usb2: add gpio handling

2017-12-12 Thread Yoshihiro Shimoda
Some R-Car SoCs (e.g. R-Car D3) doesn't have dedicated pins of VBUS
and ID. So, they may be connected to gpio pins. To handle the gpio
pins, this patch adds the handling of VBUS and ID pins instead of
dedicated pins.

Signed-off-by: Yoshihiro Shimoda 
---
 .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt |  2 +
 drivers/phy/renesas/phy-rcar-gen3-usb2.c   | 77 --
 2 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt 
b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
index 99b651b..851582f 100644
--- a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
+++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
@@ -27,6 +27,8 @@ channel as USB OTG:
 - interrupts: interrupt specifier for the PHY.
 - vbus-supply: Phandle to a regulator that provides power to the VBUS. This
   regulator will be managed during the PHY power on/off sequence.
+- renesas,vbus-gpios: use gpio to control vbus instead of dedicated pin.
+- renesas,id-gpios: use gpio to detect id instead of dedicated pin.
 
 Example (R-Car H3):
 
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 5e509a9..0b6333d 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -13,6 +13,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -100,9 +101,12 @@ struct rcar_gen3_chan {
struct phy *phy;
struct regulator *vbus;
const struct rcar_gen3_role_swap_ops *rs_ops;
+   struct gpio_desc *gpio_vbus;
+   struct gpio_desc *gpio_id;
struct work_struct work;
bool extcon_host;
bool has_otg_pins;
+   bool has_gpio;
 };
 
 static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
@@ -199,6 +203,36 @@ static void has_otg_pins_init(struct rcar_gen3_chan *ch)
   usb2_base + USB2_LINECTRL1);
 }
 
+static void gpio_enable_vbus(struct rcar_gen3_chan *ch, int vbus)
+{
+   gpiod_set_value(ch->gpio_vbus, vbus);
+}
+
+static bool gpio_check_id(struct rcar_gen3_chan *ch)
+{
+   return gpiod_get_value(ch->gpio_id);
+}
+
+static void gpio_set_host(struct rcar_gen3_chan *ch, int host)
+{
+   /* In gpio ops, this driver will modify the extcon_host by sysfs */
+   if (ch->extcon_host != !!host) {
+   ch->extcon_host = !!host;
+   schedule_work(>work);
+   }
+}
+
+static bool gpio_is_host(struct rcar_gen3_chan *ch)
+{
+   return ch->extcon_host;
+}
+
+static irqreturn_t gpio_irq_handler(struct rcar_gen3_chan *ch)
+{
+   /* Nop because the driver will get gpio value after exited */
+   return IRQ_HANDLED;
+}
+
 static void rcar_gen3_phy_usb2_work(struct work_struct *work)
 {
struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
@@ -323,7 +357,7 @@ static ssize_t role_store(struct device *dev, struct 
device_attribute *attr,
bool is_b_device;
enum phy_mode cur_mode, new_mode;
 
-   if (!ch->has_otg_pins || !ch->phy->init_count)
+   if (!(ch->has_otg_pins || ch->has_gpio) || !ch->phy->init_count)
return -EIO;
 
if (!strncmp(buf, "host", strlen("host")))
@@ -361,7 +395,7 @@ static ssize_t role_show(struct device *dev, struct 
device_attribute *attr,
 {
struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
 
-   if (!ch->has_otg_pins || !ch->phy->init_count)
+   if (!(ch->has_otg_pins || ch->has_gpio) || !ch->phy->init_count)
return -EIO;
 
return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
@@ -388,7 +422,7 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
 
/* Initialize otg part */
-   if (channel->has_otg_pins)
+   if (channel->has_otg_pins || channel->has_gpio)
rcar_gen3_init_otg(channel);
 
return 0;
@@ -489,6 +523,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void 
*_ch)
.irq_handler= has_otg_pins_irq_handler,
 };
 
+static const struct rcar_gen3_role_swap_ops gpio_ops = {
+   .set_host   = gpio_set_host,
+   .is_host= gpio_is_host,
+   .enable_vbus= gpio_enable_vbus,
+   .check_id   = gpio_check_id,
+   .irq_handler= gpio_irq_handler,
+};
+
 static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -513,9 +555,30 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device 
*pdev)
 
INIT_WORK(>work, rcar_gen3_phy_usb2_work);
 
-   /* call request_irq for OTG */
+   channel->gpio_vbus = devm_gpiod_get(dev, "renesas,vbus", GPIOD_OUT_LOW);
+   if (IS_ERR(channel->gpio_vbus) &&
+   PTR_ERR(channel->gpio_vbus) == -EPROBE_DEFER)
+   return PTR_ERR(channel->gpio_vbus);
+
+   channel->gpio_id = 

[PATCH 1/5] phy: renesas: rcar-gen3-usb2: call INIT_WORK() anyway

2017-12-12 Thread Yoshihiro Shimoda
In the future, the work struct will be used by non-irq related code.
So, this patch moves the INIT_WORK() timing.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 9c90e7d..c22d65a 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -431,10 +431,11 @@ static int rcar_gen3_phy_usb2_probe(struct 
platform_device *pdev)
if (IS_ERR(channel->base))
return PTR_ERR(channel->base);
 
+   INIT_WORK(>work, rcar_gen3_phy_usb2_work);
+
/* call request_irq for OTG */
irq = platform_get_irq(pdev, 0);
if (irq >= 0) {
-   INIT_WORK(>work, rcar_gen3_phy_usb2_work);
irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
   IRQF_SHARED, dev_name(dev), channel);
if (irq < 0)
-- 
1.9.1



[PATCH 3/5] phy: renesas: rcar-gen3-usb2: use prefix "has_otg_pins_" for dedicated pins handling

2017-12-12 Thread Yoshihiro Shimoda
To support gpio handling in the future, this patch clean-ups the code
to use prefix "has_otg_pins_" functions.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 130 ---
 1 file changed, 85 insertions(+), 45 deletions(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index beeaa30..6d6f3eb 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -93,21 +93,21 @@ struct rcar_gen3_chan {
bool has_otg_pins;
 };
 
-static void rcar_gen3_phy_usb2_work(struct work_struct *work)
+static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
 {
-   struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
-work);
+   void __iomem *usb2_base = ch->base;
+   u32 val = readl(usb2_base + USB2_LINECTRL1);
 
-   if (ch->extcon_host) {
-   extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true);
-   extcon_set_state_sync(ch->extcon, EXTCON_USB, false);
-   } else {
-   extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false);
-   extcon_set_state_sync(ch->extcon, EXTCON_USB, true);
-   }
+   dev_vdbg(>phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
+   val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
+   if (dp)
+   val |= USB2_LINECTRL1_DP_RPD;
+   if (dm)
+   val |= USB2_LINECTRL1_DM_RPD;
+   writel(val, usb2_base + USB2_LINECTRL1);
 }
 
-static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
+static void has_otg_pins_set_host(struct rcar_gen3_chan *ch, int host)
 {
void __iomem *usb2_base = ch->base;
u32 val = readl(usb2_base + USB2_COMMCTRL);
@@ -120,21 +120,27 @@ static void rcar_gen3_set_host_mode(struct rcar_gen3_chan 
*ch, int host)
writel(val, usb2_base + USB2_COMMCTRL);
 }
 
-static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
+static bool has_otg_pins_is_host(struct rcar_gen3_chan *ch)
+{
+   return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI);
+}
+
+static irqreturn_t has_otg_pins_irq_handler(struct rcar_gen3_chan *ch)
 {
void __iomem *usb2_base = ch->base;
-   u32 val = readl(usb2_base + USB2_LINECTRL1);
+   u32 status = readl(usb2_base + USB2_OBINTSTA);
+   irqreturn_t ret = IRQ_NONE;
 
-   dev_vdbg(>phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
-   val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
-   if (dp)
-   val |= USB2_LINECTRL1_DP_RPD;
-   if (dm)
-   val |= USB2_LINECTRL1_DM_RPD;
-   writel(val, usb2_base + USB2_LINECTRL1);
+   if (status & USB2_OBINT_BITS) {
+   dev_vdbg(>phy->dev, "%s: %08x\n", __func__, status);
+   writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+   ret = IRQ_HANDLED;
+   }
+
+   return ret;
 }
 
-static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
+static void has_otg_pins_enable_vbus(struct rcar_gen3_chan *ch, int vbus)
 {
void __iomem *usb2_base = ch->base;
u32 val = readl(usb2_base + USB2_ADPCTRL);
@@ -147,7 +153,7 @@ static void rcar_gen3_enable_vbus_ctrl(struct 
rcar_gen3_chan *ch, int vbus)
writel(val, usb2_base + USB2_ADPCTRL);
 }
 
-static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable)
+static void has_otg_pins_enable_irq(struct rcar_gen3_chan *ch, int enable)
 {
void __iomem *usb2_base = ch->base;
u32 val = readl(usb2_base + USB2_OBINTEN);
@@ -159,6 +165,57 @@ static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan 
*ch, int enable)
writel(val, usb2_base + USB2_OBINTEN);
 }
 
+static bool has_otg_pins_check_id(struct rcar_gen3_chan *ch)
+{
+   return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
+}
+
+static void has_otg_pins_init(struct rcar_gen3_chan *ch)
+{
+   void __iomem *usb2_base = ch->base;
+   u32 val;
+
+   val = readl(usb2_base + USB2_VBCTRL);
+   writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
+   writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+   has_otg_pins_enable_irq(ch, 1);
+   val = readl(usb2_base + USB2_ADPCTRL);
+   writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
+   val = readl(usb2_base + USB2_LINECTRL1);
+   rcar_gen3_set_linectrl(ch, 0, 0);
+   writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN,
+  usb2_base + USB2_LINECTRL1);
+}
+
+static void rcar_gen3_phy_usb2_work(struct work_struct *work)
+{
+   struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
+work);
+
+   if (ch->extcon_host) {
+   extcon_set_state_sync(ch->extcon, 

[PATCH 1/5] phy: renesas: rcar-gen3-usb2: call INIT_WORK() anyway

2017-12-12 Thread Yoshihiro Shimoda
In the future, the work struct will be used by non-irq related code.
So, this patch moves the INIT_WORK() timing.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 9c90e7d..c22d65a 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -431,10 +431,11 @@ static int rcar_gen3_phy_usb2_probe(struct 
platform_device *pdev)
if (IS_ERR(channel->base))
return PTR_ERR(channel->base);
 
+   INIT_WORK(>work, rcar_gen3_phy_usb2_work);
+
/* call request_irq for OTG */
irq = platform_get_irq(pdev, 0);
if (irq >= 0) {
-   INIT_WORK(>work, rcar_gen3_phy_usb2_work);
irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
   IRQF_SHARED, dev_name(dev), channel);
if (irq < 0)
-- 
1.9.1



[PATCH 3/5] phy: renesas: rcar-gen3-usb2: use prefix "has_otg_pins_" for dedicated pins handling

2017-12-12 Thread Yoshihiro Shimoda
To support gpio handling in the future, this patch clean-ups the code
to use prefix "has_otg_pins_" functions.

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 130 ---
 1 file changed, 85 insertions(+), 45 deletions(-)

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c 
b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index beeaa30..6d6f3eb 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -93,21 +93,21 @@ struct rcar_gen3_chan {
bool has_otg_pins;
 };
 
-static void rcar_gen3_phy_usb2_work(struct work_struct *work)
+static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
 {
-   struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
-work);
+   void __iomem *usb2_base = ch->base;
+   u32 val = readl(usb2_base + USB2_LINECTRL1);
 
-   if (ch->extcon_host) {
-   extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true);
-   extcon_set_state_sync(ch->extcon, EXTCON_USB, false);
-   } else {
-   extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false);
-   extcon_set_state_sync(ch->extcon, EXTCON_USB, true);
-   }
+   dev_vdbg(>phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
+   val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
+   if (dp)
+   val |= USB2_LINECTRL1_DP_RPD;
+   if (dm)
+   val |= USB2_LINECTRL1_DM_RPD;
+   writel(val, usb2_base + USB2_LINECTRL1);
 }
 
-static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
+static void has_otg_pins_set_host(struct rcar_gen3_chan *ch, int host)
 {
void __iomem *usb2_base = ch->base;
u32 val = readl(usb2_base + USB2_COMMCTRL);
@@ -120,21 +120,27 @@ static void rcar_gen3_set_host_mode(struct rcar_gen3_chan 
*ch, int host)
writel(val, usb2_base + USB2_COMMCTRL);
 }
 
-static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
+static bool has_otg_pins_is_host(struct rcar_gen3_chan *ch)
+{
+   return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI);
+}
+
+static irqreturn_t has_otg_pins_irq_handler(struct rcar_gen3_chan *ch)
 {
void __iomem *usb2_base = ch->base;
-   u32 val = readl(usb2_base + USB2_LINECTRL1);
+   u32 status = readl(usb2_base + USB2_OBINTSTA);
+   irqreturn_t ret = IRQ_NONE;
 
-   dev_vdbg(>phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
-   val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
-   if (dp)
-   val |= USB2_LINECTRL1_DP_RPD;
-   if (dm)
-   val |= USB2_LINECTRL1_DM_RPD;
-   writel(val, usb2_base + USB2_LINECTRL1);
+   if (status & USB2_OBINT_BITS) {
+   dev_vdbg(>phy->dev, "%s: %08x\n", __func__, status);
+   writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+   ret = IRQ_HANDLED;
+   }
+
+   return ret;
 }
 
-static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
+static void has_otg_pins_enable_vbus(struct rcar_gen3_chan *ch, int vbus)
 {
void __iomem *usb2_base = ch->base;
u32 val = readl(usb2_base + USB2_ADPCTRL);
@@ -147,7 +153,7 @@ static void rcar_gen3_enable_vbus_ctrl(struct 
rcar_gen3_chan *ch, int vbus)
writel(val, usb2_base + USB2_ADPCTRL);
 }
 
-static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable)
+static void has_otg_pins_enable_irq(struct rcar_gen3_chan *ch, int enable)
 {
void __iomem *usb2_base = ch->base;
u32 val = readl(usb2_base + USB2_OBINTEN);
@@ -159,6 +165,57 @@ static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan 
*ch, int enable)
writel(val, usb2_base + USB2_OBINTEN);
 }
 
+static bool has_otg_pins_check_id(struct rcar_gen3_chan *ch)
+{
+   return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
+}
+
+static void has_otg_pins_init(struct rcar_gen3_chan *ch)
+{
+   void __iomem *usb2_base = ch->base;
+   u32 val;
+
+   val = readl(usb2_base + USB2_VBCTRL);
+   writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
+   writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+   has_otg_pins_enable_irq(ch, 1);
+   val = readl(usb2_base + USB2_ADPCTRL);
+   writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
+   val = readl(usb2_base + USB2_LINECTRL1);
+   rcar_gen3_set_linectrl(ch, 0, 0);
+   writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN,
+  usb2_base + USB2_LINECTRL1);
+}
+
+static void rcar_gen3_phy_usb2_work(struct work_struct *work)
+{
+   struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
+work);
+
+   if (ch->extcon_host) {
+   extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true);
+

  1   2   3   4   5   6   7   8   9   10   >