Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Gang He



>>> 
> On 2018/1/11 15:19, Gang He wrote:
>> 
>> 
>> 
>
>>> On 2018/1/11 12:31, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/11 11:33, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> On 2018/1/11 10:07, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/10 18:14, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> On 2018/1/10 17:05, Gang He wrote:
 Hi Changwei,


>>>
> Hi Gang,
>
> On 2017/12/14 13:16, Gang He wrote:
>> As you know, ocfs2 has support trim the underlying disk via
>> fstrim command. But there is a problem, ocfs2 is a shared disk
>> cluster file system, if the user configures a scheduled fstrim
>> job on each file system node, this will trigger multiple nodes
>> trim a shared disk simultaneously, it is very wasteful for CPU
>> and IO consumption, also might negatively affect the lifetime
>> of poor-quality SSD devices.
>> Then, we introduce a trimfs dlm lock to communicate with each
>> other in this case, which will make only one fstrim command to
>> do the trimming on a shared disk among the cluster, the fstrim
>> commands from the other nodes should wait for the first fstrim
>> to finish and returned success directly, to avoid running a the
>> same trim on the shared disk again.
>>
>> Compare with first version, I change the fstrim commands' 
>> returned
>> value and behavior in case which meets a fstrim command is 
>> running
>> on a shared disk.
>>
>> Signed-off-by: Gang He 
>> ---
>> fs/ocfs2/alloc.c | 44 
>> 
>> 1 file changed, 44 insertions(+)
>>
>> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
>> index ab5105f..5c9c3e2 100644
>> --- a/fs/ocfs2/alloc.c
>> +++ b/fs/ocfs2/alloc.c
>> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
>> struct
> fstrim_range *range)
>>  struct buffer_head *gd_bh = NULL;
>>  struct ocfs2_dinode *main_bm;
>>  struct ocfs2_group_desc *gd = NULL;
>> +struct ocfs2_trim_fs_info info, *pinfo = NULL;
>
> I think *pinfo* is not necessary.
 This pointer is necessary, since it can be NULL or non-NULL depend 
 on the
>>> code logic.
>>>
>>> This point is OK for me.
>>>

>> 
>>  start = range->start >> osb->s_clustersize_bits;
>>  len = range->len >> osb->s_clustersize_bits;
>> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
>> struct
> fstrim_range *range)
>> 
>>  trace_ocfs2_trim_fs(start, len, minlen);
>> 
>> +ocfs2_trim_fs_lock_res_init(osb);
>> +ret = ocfs2_trim_fs_lock(osb, NULL, 1);
>
> I don't get why try to lock here and if fails, acquire the same 
> lock again
> later but wait until granted.
 Please think about the user case, the patch is only used to handle 
 this
>>> case.
 When the administer configures a fstrim schedule task on each 
 node, then
>>> each node will trigger a fstrim on shared disks concurrently.
 In this case, we should avoid duplicated fstrim on a shared disk 
 since this
>>> will waste CPU/IO resources and affect SSD lifetime sometimes.
>>>
>>> I'm not worrying about that trimfs will affect SSD's lifetime quite 
>>> a lot,
>>> since physical-logical address converting table resides in RAM 
>>> while SSD is
>>> working.
>>> And that table won't be at a big scale. My point here is not 
>>> affecting this
>>> patch. Just a tip here.
>> This depend on SSD firmware implementation, but for secure-trim, it 
>> really
> possibly affect SSD lifetime.
>>
 Firstly, we use try_lock to get fstrim dlm lock to identify if 
 there is any
>>> other node which is doing fstrim on the disk.
 If not, this node is the first one, this node should do fstrim 
 operation on
>>> the disk.
 If yes, this node is not the first one, this node should wait 
 until the
>>> 

Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Gang He



>>> 
> On 2018/1/11 15:19, Gang He wrote:
>> 
>> 
>> 
>
>>> On 2018/1/11 12:31, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/11 11:33, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> On 2018/1/11 10:07, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/10 18:14, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> On 2018/1/10 17:05, Gang He wrote:
 Hi Changwei,


>>>
> Hi Gang,
>
> On 2017/12/14 13:16, Gang He wrote:
>> As you know, ocfs2 has support trim the underlying disk via
>> fstrim command. But there is a problem, ocfs2 is a shared disk
>> cluster file system, if the user configures a scheduled fstrim
>> job on each file system node, this will trigger multiple nodes
>> trim a shared disk simultaneously, it is very wasteful for CPU
>> and IO consumption, also might negatively affect the lifetime
>> of poor-quality SSD devices.
>> Then, we introduce a trimfs dlm lock to communicate with each
>> other in this case, which will make only one fstrim command to
>> do the trimming on a shared disk among the cluster, the fstrim
>> commands from the other nodes should wait for the first fstrim
>> to finish and returned success directly, to avoid running a the
>> same trim on the shared disk again.
>>
>> Compare with first version, I change the fstrim commands' 
>> returned
>> value and behavior in case which meets a fstrim command is 
>> running
>> on a shared disk.
>>
>> Signed-off-by: Gang He 
>> ---
>> fs/ocfs2/alloc.c | 44 
>> 
>> 1 file changed, 44 insertions(+)
>>
>> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
>> index ab5105f..5c9c3e2 100644
>> --- a/fs/ocfs2/alloc.c
>> +++ b/fs/ocfs2/alloc.c
>> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
>> struct
> fstrim_range *range)
>>  struct buffer_head *gd_bh = NULL;
>>  struct ocfs2_dinode *main_bm;
>>  struct ocfs2_group_desc *gd = NULL;
>> +struct ocfs2_trim_fs_info info, *pinfo = NULL;
>
> I think *pinfo* is not necessary.
 This pointer is necessary, since it can be NULL or non-NULL depend 
 on the
>>> code logic.
>>>
>>> This point is OK for me.
>>>

>> 
>>  start = range->start >> osb->s_clustersize_bits;
>>  len = range->len >> osb->s_clustersize_bits;
>> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
>> struct
> fstrim_range *range)
>> 
>>  trace_ocfs2_trim_fs(start, len, minlen);
>> 
>> +ocfs2_trim_fs_lock_res_init(osb);
>> +ret = ocfs2_trim_fs_lock(osb, NULL, 1);
>
> I don't get why try to lock here and if fails, acquire the same 
> lock again
> later but wait until granted.
 Please think about the user case, the patch is only used to handle 
 this
>>> case.
 When the administer configures a fstrim schedule task on each 
 node, then
>>> each node will trigger a fstrim on shared disks concurrently.
 In this case, we should avoid duplicated fstrim on a shared disk 
 since this
>>> will waste CPU/IO resources and affect SSD lifetime sometimes.
>>>
>>> I'm not worrying about that trimfs will affect SSD's lifetime quite 
>>> a lot,
>>> since physical-logical address converting table resides in RAM 
>>> while SSD is
>>> working.
>>> And that table won't be at a big scale. My point here is not 
>>> affecting this
>>> patch. Just a tip here.
>> This depend on SSD firmware implementation, but for secure-trim, it 
>> really
> possibly affect SSD lifetime.
>>
 Firstly, we use try_lock to get fstrim dlm lock to identify if 
 there is any
>>> other node which is doing fstrim on the disk.
 If not, this node is the first one, this node should do fstrim 
 operation on
>>> the disk.
 If yes, this node is not the first one, this node should wait 
 until the
>>> first node is 

Re: [PATCH 0/7] ARM: dts: STi: Fix DT dtc warnings

2018-01-10 Thread Patrice CHOTARD
HI Arnd

On 01/10/2018 09:52 PM, Arnd Bergmann wrote:
> On Wed, Jan 10, 2018 at 6:17 PM, Patrice CHOTARD  
> wrote:
>> Hi Arnd
>>
>> On 01/10/2018 04:52 PM, Arnd Bergmann wrote:
>>> On Wed, Jan 10, 2018 at 9:21 AM,   wrote:
 From: Patrice Chotard 

 This series fixes all dtc warnings related to STi platforms dt files.
 It has been triggered by Rob Herring [1]

 [1] https://www.spinics.net/lists/devicetree/msg206209.html

 For most of implicated node, a simple move outside the soc node
 solves the warnings.

 Patrice Chotard (7):
 ARM: dts: STi: fix bindings notation
 ARM: dts: STi: Add gpio polarity for "hdmi,hpd-gpio" property
 ARM: dts: STi: Move clocks without reg outside soc
 ARM: dts: STi: Move leds node outside soc node
 ARM: dts: STi: Move usb2_picophyX nodes without reg out of soc
 ARM: dts: STi: Move sound related nodes without reg out of soc
 ARM: dts: STi: Add fake reg property for sti-display-subsystem
>>>
>>> Thanks a lot for addressing these!
>>>
>>> As far as I can tell, there is one patch in particular that addresses a 
>>> warning
>>> we get at the default warning level: "ARM: dts: STi: Add gpio polarity for
>>> "hdmi,hpd-gpio" property". Should we merge that one for 4.15 to get closer
>>> to a clean build again? I'm not sure whether we can address the other
>>
>> How do you want to proceed with this particular patch ?
>> Do you want me to send a pull-request with this patch ?
>>
>> Patrice
> 
> I'd just pick it up directly into the arm-soc fixes branch if that
> works for you.

Perfect ;-)

Thanks

Patrice

> 
> Arnd
> 

Re: [PATCH 0/7] ARM: dts: STi: Fix DT dtc warnings

2018-01-10 Thread Patrice CHOTARD
HI Arnd

On 01/10/2018 09:52 PM, Arnd Bergmann wrote:
> On Wed, Jan 10, 2018 at 6:17 PM, Patrice CHOTARD  
> wrote:
>> Hi Arnd
>>
>> On 01/10/2018 04:52 PM, Arnd Bergmann wrote:
>>> On Wed, Jan 10, 2018 at 9:21 AM,   wrote:
 From: Patrice Chotard 

 This series fixes all dtc warnings related to STi platforms dt files.
 It has been triggered by Rob Herring [1]

 [1] https://www.spinics.net/lists/devicetree/msg206209.html

 For most of implicated node, a simple move outside the soc node
 solves the warnings.

 Patrice Chotard (7):
 ARM: dts: STi: fix bindings notation
 ARM: dts: STi: Add gpio polarity for "hdmi,hpd-gpio" property
 ARM: dts: STi: Move clocks without reg outside soc
 ARM: dts: STi: Move leds node outside soc node
 ARM: dts: STi: Move usb2_picophyX nodes without reg out of soc
 ARM: dts: STi: Move sound related nodes without reg out of soc
 ARM: dts: STi: Add fake reg property for sti-display-subsystem
>>>
>>> Thanks a lot for addressing these!
>>>
>>> As far as I can tell, there is one patch in particular that addresses a 
>>> warning
>>> we get at the default warning level: "ARM: dts: STi: Add gpio polarity for
>>> "hdmi,hpd-gpio" property". Should we merge that one for 4.15 to get closer
>>> to a clean build again? I'm not sure whether we can address the other
>>
>> How do you want to proceed with this particular patch ?
>> Do you want me to send a pull-request with this patch ?
>>
>> Patrice
> 
> I'd just pick it up directly into the arm-soc fixes branch if that
> works for you.

Perfect ;-)

Thanks

Patrice

> 
> Arnd
> 

Re: [RESEND PATCH v11 1/2] sched/deadline: Add support for SD_PREFER_SIBLING on find_later_rq()

2018-01-10 Thread Byungchul Park

On 1/11/2018 2:22 AM, kbuild test robot wrote:

Hi Byungchul,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on tip/sched/core]
[also build test WARNING on v4.15-rc7 next-20180110]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Byungchul-Park/sched-deadline-Add-support-for-SD_PREFER_SIBLING-on-find_later_rq/20180110-225946
reproduce:
 # apt-get install sparse
 make ARCH=x86_64 allmodconfig
 make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/deadline.c:1124:5: sparse: symbol 'grub_reclaim' was not 
declared. Should it be
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/deadline.c:1916:9: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)

kernel/sched/deadline.c:1857:55: sparse: incorrect type in argument 1 
(different modifiers) @@ expected struct sched_domain @@ got structstruct 
sched_domain @@

kernel/sched/deadline.c:1857:55: expected struct sched_domain
kernel/sched/deadline.c:1857:55: got struct sched_domain const
kernel/sched/deadline.c:1858:64: sparse: incorrect type in argument 1 
(different modifiers) @@ expected struct sched_domain @@ got structstruct 
sched_domain @@
kernel/sched/deadline.c:1858:64: expected struct sched_domain
kernel/sched/deadline.c:1858:64: got struct sched_domain const
kernel/sched/deadline.c:563:9: sparse: context imbalance in 
'dl_task_offline_migration' - unexpected unlock
kernel/sched/deadline.c:2060:9: sparse: context imbalance in 
'find_lock_later_rq' - different lock contexts for basic block
kernel/sched/deadline.c:2155:23: sparse: context imbalance in 
'push_dl_task' - unexpected unlock
kernel/sched/sched.h:1856:17: sparse: context imbalance in 'pull_dl_task' - 
unexpected unlock
kernel/sched/deadline.c: In function 'find_cpu':
kernel/sched/deadline.c:1857:48: warning: passing argument 1 of 
'sched_domain_span' discards 'const' qualifier from pointer target type
 const struct cpumask = sched_domain_span(sd);
 ^~
In file included from kernel/sched/sched.h:6:0,
 from kernel/sched/deadline.c:18:
include/linux/sched/topology.h:160:31: note: expected 'struct sched_domain 
but argument is of type 'const struct sched_domain
 static inline struct cpumask sched_domain
 ^
kernel/sched/deadline.c:1858:57: warning: passing argument 1 of 
'sched_domain_span' discards 'const' qualifier from pointer target type
 const struct cpumask = prefer sched_domain_span(prefer) : NULL;
 ^~
In file included from kernel/sched/sched.h:6:0,
 from kernel/sched/deadline.c:18:
include/linux/sched/topology.h:160:31: note: expected 'struct sched_domain 
but argument is of type 'const struct sched_domain
 static inline struct cpumask sched_domain
 ^

vim +1857 kernel/sched/deadline.c

   1849 
   1850 /*
   1851  * Find the first cpu in: mask & sd & ~prefer
   1852  */
   1853 static int find_cpu(const struct cpumask *mask,
   1854 const struct sched_domain *sd,
   1855 const struct sched_domain *prefer)
   1856 {

1857const struct cpumask *sds = sched_domain_span(sd);


Thanks a lot.

I will fix and respin it.

I'm gonna change prototype of sched_domain_span() rather than
find_cpu() to avoid the warning. Is it ok to fix it that way?


   1858 const struct cpumask *ps  = prefer ? sched_domain_span(prefer) 
: NULL;
   1859 int cpu;
  

Re: [RESEND PATCH v11 1/2] sched/deadline: Add support for SD_PREFER_SIBLING on find_later_rq()

2018-01-10 Thread Byungchul Park

On 1/11/2018 2:22 AM, kbuild test robot wrote:

Hi Byungchul,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on tip/sched/core]
[also build test WARNING on v4.15-rc7 next-20180110]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Byungchul-Park/sched-deadline-Add-support-for-SD_PREFER_SIBLING-on-find_later_rq/20180110-225946
reproduce:
 # apt-get install sparse
 make ARCH=x86_64 allmodconfig
 make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/deadline.c:1124:5: sparse: symbol 'grub_reclaim' was not 
declared. Should it be
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/deadline.c:1916:9: sparse: incompatible types in comparison 
expression (different address spaces)
kernel/sched/sched.h:2104:16: sparse: incompatible types in comparison 
expression (different address spaces)

kernel/sched/deadline.c:1857:55: sparse: incorrect type in argument 1 
(different modifiers) @@ expected struct sched_domain @@ got structstruct 
sched_domain @@

kernel/sched/deadline.c:1857:55: expected struct sched_domain
kernel/sched/deadline.c:1857:55: got struct sched_domain const
kernel/sched/deadline.c:1858:64: sparse: incorrect type in argument 1 
(different modifiers) @@ expected struct sched_domain @@ got structstruct 
sched_domain @@
kernel/sched/deadline.c:1858:64: expected struct sched_domain
kernel/sched/deadline.c:1858:64: got struct sched_domain const
kernel/sched/deadline.c:563:9: sparse: context imbalance in 
'dl_task_offline_migration' - unexpected unlock
kernel/sched/deadline.c:2060:9: sparse: context imbalance in 
'find_lock_later_rq' - different lock contexts for basic block
kernel/sched/deadline.c:2155:23: sparse: context imbalance in 
'push_dl_task' - unexpected unlock
kernel/sched/sched.h:1856:17: sparse: context imbalance in 'pull_dl_task' - 
unexpected unlock
kernel/sched/deadline.c: In function 'find_cpu':
kernel/sched/deadline.c:1857:48: warning: passing argument 1 of 
'sched_domain_span' discards 'const' qualifier from pointer target type
 const struct cpumask = sched_domain_span(sd);
 ^~
In file included from kernel/sched/sched.h:6:0,
 from kernel/sched/deadline.c:18:
include/linux/sched/topology.h:160:31: note: expected 'struct sched_domain 
but argument is of type 'const struct sched_domain
 static inline struct cpumask sched_domain
 ^
kernel/sched/deadline.c:1858:57: warning: passing argument 1 of 
'sched_domain_span' discards 'const' qualifier from pointer target type
 const struct cpumask = prefer sched_domain_span(prefer) : NULL;
 ^~
In file included from kernel/sched/sched.h:6:0,
 from kernel/sched/deadline.c:18:
include/linux/sched/topology.h:160:31: note: expected 'struct sched_domain 
but argument is of type 'const struct sched_domain
 static inline struct cpumask sched_domain
 ^

vim +1857 kernel/sched/deadline.c

   1849 
   1850 /*
   1851  * Find the first cpu in: mask & sd & ~prefer
   1852  */
   1853 static int find_cpu(const struct cpumask *mask,
   1854 const struct sched_domain *sd,
   1855 const struct sched_domain *prefer)
   1856 {

1857const struct cpumask *sds = sched_domain_span(sd);


Thanks a lot.

I will fix and respin it.

I'm gonna change prototype of sched_domain_span() rather than
find_cpu() to avoid the warning. Is it ok to fix it that way?


   1858 const struct cpumask *ps  = prefer ? sched_domain_span(prefer) 
: NULL;
   1859 int cpu;
  

Re: [PATCH 6/6] crypto: stm32-cryp: convert to the new crypto engine API

2018-01-10 Thread Fabien DESSENNE
(Adding my tested by)


On 10/01/18 15:25, Fabien DESSENNE wrote:
>
> On 03/01/18 21:11, Corentin Labbe wrote:
>> This patch convert the stm32-cryp driver to the new crypto engine API.
>> Signed-off-by: Corentin Labbe 

Tested-by: Fabien Dessenne 

>> ---
>>drivers/crypto/stm32/stm32-cryp.c | 21 -
>>1 file changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/crypto/stm32/stm32-cryp.c 
>> b/drivers/crypto/stm32/stm32-cryp.c
>> index cf1dddbeaa2c..99e0473ef247 100644
>> --- a/drivers/crypto/stm32/stm32-cryp.c
>> +++ b/drivers/crypto/stm32/stm32-cryp.c
>> @@ -91,6 +91,7 @@
>>#define _walked_out (cryp->out_walk.offset - 
>> cryp->out_sg->offset)
>>
>>struct stm32_cryp_ctx {
>> +struct crypto_engine_reqctx enginectx;
>>  struct stm32_cryp   *cryp;
>>  int keylen;
>>  u32 key[AES_KEYSIZE_256 / sizeof(u32)];
>> @@ -494,10 +495,20 @@ static int stm32_cryp_cpu_start(struct stm32_cryp 
>> *cryp)
>>  return 0;
>>}
>>
>> +static int stm32_cryp_cipher_one_req(struct crypto_engine *engine,
>> + void *areq);
> Merge these 2 lines in a single one
>
>> +static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
>> + void *areq);
>> +
>>static int stm32_cryp_cra_init(struct crypto_tfm *tfm)
>>{
>> +struct stm32_cryp_ctx *ctx = crypto_tfm_ctx(tfm);
>> +
>>  tfm->crt_ablkcipher.reqsize = sizeof(struct stm32_cryp_reqctx);
>>
>> +ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req;
>> +ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req;
>> +ctx->enginectx.op.unprepare_request = NULL;
>>  return 0;
>>}
>>
>> @@ -695,14 +706,17 @@ static int stm32_cryp_prepare_req(struct crypto_engine 
>> *engine,
>>}
>>
>>static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
>> - struct ablkcipher_request *req)
>> + void *areq)
>>{
>> +struct ablkcipher_request *req = container_of(areq, struct 
>> ablkcipher_request, base);
>   > 80 characters (CHECKPATCH)
>
>> +
>>  return stm32_cryp_prepare_req(engine, req);
>>}
>>
>>static int stm32_cryp_cipher_one_req(struct crypto_engine *engine,
>> - struct ablkcipher_request *req)
>> + void *areq)
> Merge these 2 lines in a single one
>
>>{
>> +struct ablkcipher_request *req = container_of(areq, struct 
>> ablkcipher_request, base);
>   > 80 characters (CHECKPATCH)
>
>>  struct stm32_cryp_ctx *ctx = crypto_ablkcipher_ctx(
>>  crypto_ablkcipher_reqtfm(req));
>>  struct stm32_cryp *cryp = ctx->cryp;
>> @@ -1104,9 +1118,6 @@ static int stm32_cryp_probe(struct platform_device 
>> *pdev)
>>  goto err_engine1;
>>  }
>>
>> -cryp->engine->prepare_cipher_request = stm32_cryp_prepare_cipher_req;
>> -cryp->engine->cipher_one_request = stm32_cryp_cipher_one_req;
>> -
>>  ret = crypto_engine_start(cryp->engine);
>>  if (ret) {
>>  dev_err(dev, "Could not start crypto engine\n");


Re: [PATCH 6/6] crypto: stm32-cryp: convert to the new crypto engine API

2018-01-10 Thread Fabien DESSENNE
(Adding my tested by)


On 10/01/18 15:25, Fabien DESSENNE wrote:
>
> On 03/01/18 21:11, Corentin Labbe wrote:
>> This patch convert the stm32-cryp driver to the new crypto engine API.
>> Signed-off-by: Corentin Labbe 

Tested-by: Fabien Dessenne 

>> ---
>>drivers/crypto/stm32/stm32-cryp.c | 21 -
>>1 file changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/crypto/stm32/stm32-cryp.c 
>> b/drivers/crypto/stm32/stm32-cryp.c
>> index cf1dddbeaa2c..99e0473ef247 100644
>> --- a/drivers/crypto/stm32/stm32-cryp.c
>> +++ b/drivers/crypto/stm32/stm32-cryp.c
>> @@ -91,6 +91,7 @@
>>#define _walked_out (cryp->out_walk.offset - 
>> cryp->out_sg->offset)
>>
>>struct stm32_cryp_ctx {
>> +struct crypto_engine_reqctx enginectx;
>>  struct stm32_cryp   *cryp;
>>  int keylen;
>>  u32 key[AES_KEYSIZE_256 / sizeof(u32)];
>> @@ -494,10 +495,20 @@ static int stm32_cryp_cpu_start(struct stm32_cryp 
>> *cryp)
>>  return 0;
>>}
>>
>> +static int stm32_cryp_cipher_one_req(struct crypto_engine *engine,
>> + void *areq);
> Merge these 2 lines in a single one
>
>> +static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
>> + void *areq);
>> +
>>static int stm32_cryp_cra_init(struct crypto_tfm *tfm)
>>{
>> +struct stm32_cryp_ctx *ctx = crypto_tfm_ctx(tfm);
>> +
>>  tfm->crt_ablkcipher.reqsize = sizeof(struct stm32_cryp_reqctx);
>>
>> +ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req;
>> +ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req;
>> +ctx->enginectx.op.unprepare_request = NULL;
>>  return 0;
>>}
>>
>> @@ -695,14 +706,17 @@ static int stm32_cryp_prepare_req(struct crypto_engine 
>> *engine,
>>}
>>
>>static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
>> - struct ablkcipher_request *req)
>> + void *areq)
>>{
>> +struct ablkcipher_request *req = container_of(areq, struct 
>> ablkcipher_request, base);
>   > 80 characters (CHECKPATCH)
>
>> +
>>  return stm32_cryp_prepare_req(engine, req);
>>}
>>
>>static int stm32_cryp_cipher_one_req(struct crypto_engine *engine,
>> - struct ablkcipher_request *req)
>> + void *areq)
> Merge these 2 lines in a single one
>
>>{
>> +struct ablkcipher_request *req = container_of(areq, struct 
>> ablkcipher_request, base);
>   > 80 characters (CHECKPATCH)
>
>>  struct stm32_cryp_ctx *ctx = crypto_ablkcipher_ctx(
>>  crypto_ablkcipher_reqtfm(req));
>>  struct stm32_cryp *cryp = ctx->cryp;
>> @@ -1104,9 +1118,6 @@ static int stm32_cryp_probe(struct platform_device 
>> *pdev)
>>  goto err_engine1;
>>  }
>>
>> -cryp->engine->prepare_cipher_request = stm32_cryp_prepare_cipher_req;
>> -cryp->engine->cipher_one_request = stm32_cryp_cipher_one_req;
>> -
>>  ret = crypto_engine_start(cryp->engine);
>>  if (ret) {
>>  dev_err(dev, "Could not start crypto engine\n");


Re: [PATCH 2/6] crypto: engine - Permit to enqueue all async requests

2018-01-10 Thread Fabien DESSENNE
(adding my tested by)


On 10/01/18 15:19, Fabien DESSENNE wrote:
> On 03/01/18 21:11, Corentin Labbe wrote:
>> The crypto engine could actually only enqueue hash and ablkcipher request.
>> This patch permit it to enqueue any type of crypto_async_request.
>>
>> Signed-off-by: Corentin Labbe 

Tested-by: Fabien Dessenne 

>> ---
>>crypto/crypto_engine.c  | 230 
>> 
>>include/crypto/engine.h |  59 +++--
>>2 files changed, 148 insertions(+), 141 deletions(-)
>>
>> diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
>> index 61e7c4e02fd2..036270b61648 100644
>> --- a/crypto/crypto_engine.c
>> +++ b/crypto/crypto_engine.c
>> @@ -15,7 +15,6 @@
>>#include 
>>#include 
>>#include 
>> -#include 
>>#include 
>>#include "internal.h"
>>
>> @@ -34,11 +33,10 @@ static void crypto_pump_requests(struct crypto_engine 
>> *engine,
>>   bool in_kthread)
>>{
>>  struct crypto_async_request *async_req, *backlog;
>> -struct ahash_request *hreq;
>> -struct ablkcipher_request *breq;
>>  unsigned long flags;
>>  bool was_busy = false;
>> -int ret, rtype;
>> +int ret;
>> +struct crypto_engine_reqctx *enginectx;
>>
>>  spin_lock_irqsave(>queue_lock, flags);
>>
>> @@ -94,7 +92,6 @@ static void crypto_pump_requests(struct crypto_engine 
>> *engine,
>>
>>  spin_unlock_irqrestore(>queue_lock, flags);
>>
>> -rtype = crypto_tfm_alg_type(engine->cur_req->tfm);
>>  /* Until here we get the request need to be encrypted successfully */
>>  if (!was_busy && engine->prepare_crypt_hardware) {
>>  ret = engine->prepare_crypt_hardware(engine);
>> @@ -104,57 +101,31 @@ static void crypto_pump_requests(struct crypto_engine 
>> *engine,
>>  }
>>  }
>>
>> -switch (rtype) {
>> -case CRYPTO_ALG_TYPE_AHASH:
>> -hreq = ahash_request_cast(engine->cur_req);
>> -if (engine->prepare_hash_request) {
>> -ret = engine->prepare_hash_request(engine, hreq);
>> -if (ret) {
>> -dev_err(engine->dev, "failed to prepare 
>> request: %d\n",
>> -ret);
>> -goto req_err;
>> -}
>> -engine->cur_req_prepared = true;
>> -}
>> -ret = engine->hash_one_request(engine, hreq);
>> -if (ret) {
>> -dev_err(engine->dev, "failed to hash one request from 
>> queue\n");
>> -goto req_err;
>> -}
>> -return;
>> -case CRYPTO_ALG_TYPE_ABLKCIPHER:
>> -breq = ablkcipher_request_cast(engine->cur_req);
>> -if (engine->prepare_cipher_request) {
>> -ret = engine->prepare_cipher_request(engine, breq);
>> -if (ret) {
>> -dev_err(engine->dev, "failed to prepare 
>> request: %d\n",
>> -ret);
>> -goto req_err;
>> -}
>> -engine->cur_req_prepared = true;
>> -}
>> -ret = engine->cipher_one_request(engine, breq);
>> +enginectx = crypto_tfm_ctx(async_req->tfm);
>> +
>> +if (enginectx->op.prepare_request) {
>> +ret = enginectx->op.prepare_request(engine, async_req);
>>  if (ret) {
>> -dev_err(engine->dev, "failed to cipher one request from 
>> queue\n");
>> +dev_err(engine->dev, "failed to prepare request: %d\n",
>> +ret);
>>  goto req_err;
>>  }
>> -return;
>> -default:
>> -dev_err(engine->dev, "failed to prepare request of unknown 
>> type\n");
>> -return;
>> +engine->cur_req_prepared = true;
>> +}
>> +if (!enginectx->op.do_one_request) {
>> +dev_err(engine->dev, "failed to do request\n");
>> +ret = -EINVAL;
>> +goto req_err;
>> +}
>> +ret = enginectx->op.do_one_request(engine, async_req);
>> +if (ret) {
>> +dev_err(engine->dev, "Failed to do one request from queue: 
>> %d\n", ret);
>> +goto req_err;
>>  }
>> +return;
>>
>>req_err:
>> -switch (rtype) {
>> -case CRYPTO_ALG_TYPE_AHASH:
>> -hreq = ahash_request_cast(engine->cur_req);
>> -crypto_finalize_hash_request(engine, hreq, ret);
>> -break;
>> -case CRYPTO_ALG_TYPE_ABLKCIPHER:
>> -breq = ablkcipher_request_cast(engine->cur_req);
>> -crypto_finalize_cipher_request(engine, breq, ret);
>> -break;
>> -}
>> +crypto_finalize_request(engine, async_req, ret);
>>  return;
>>
>>out:
>> @@ 

Re: [PATCH 2/6] crypto: engine - Permit to enqueue all async requests

2018-01-10 Thread Fabien DESSENNE
(adding my tested by)


On 10/01/18 15:19, Fabien DESSENNE wrote:
> On 03/01/18 21:11, Corentin Labbe wrote:
>> The crypto engine could actually only enqueue hash and ablkcipher request.
>> This patch permit it to enqueue any type of crypto_async_request.
>>
>> Signed-off-by: Corentin Labbe 

Tested-by: Fabien Dessenne 

>> ---
>>crypto/crypto_engine.c  | 230 
>> 
>>include/crypto/engine.h |  59 +++--
>>2 files changed, 148 insertions(+), 141 deletions(-)
>>
>> diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
>> index 61e7c4e02fd2..036270b61648 100644
>> --- a/crypto/crypto_engine.c
>> +++ b/crypto/crypto_engine.c
>> @@ -15,7 +15,6 @@
>>#include 
>>#include 
>>#include 
>> -#include 
>>#include 
>>#include "internal.h"
>>
>> @@ -34,11 +33,10 @@ static void crypto_pump_requests(struct crypto_engine 
>> *engine,
>>   bool in_kthread)
>>{
>>  struct crypto_async_request *async_req, *backlog;
>> -struct ahash_request *hreq;
>> -struct ablkcipher_request *breq;
>>  unsigned long flags;
>>  bool was_busy = false;
>> -int ret, rtype;
>> +int ret;
>> +struct crypto_engine_reqctx *enginectx;
>>
>>  spin_lock_irqsave(>queue_lock, flags);
>>
>> @@ -94,7 +92,6 @@ static void crypto_pump_requests(struct crypto_engine 
>> *engine,
>>
>>  spin_unlock_irqrestore(>queue_lock, flags);
>>
>> -rtype = crypto_tfm_alg_type(engine->cur_req->tfm);
>>  /* Until here we get the request need to be encrypted successfully */
>>  if (!was_busy && engine->prepare_crypt_hardware) {
>>  ret = engine->prepare_crypt_hardware(engine);
>> @@ -104,57 +101,31 @@ static void crypto_pump_requests(struct crypto_engine 
>> *engine,
>>  }
>>  }
>>
>> -switch (rtype) {
>> -case CRYPTO_ALG_TYPE_AHASH:
>> -hreq = ahash_request_cast(engine->cur_req);
>> -if (engine->prepare_hash_request) {
>> -ret = engine->prepare_hash_request(engine, hreq);
>> -if (ret) {
>> -dev_err(engine->dev, "failed to prepare 
>> request: %d\n",
>> -ret);
>> -goto req_err;
>> -}
>> -engine->cur_req_prepared = true;
>> -}
>> -ret = engine->hash_one_request(engine, hreq);
>> -if (ret) {
>> -dev_err(engine->dev, "failed to hash one request from 
>> queue\n");
>> -goto req_err;
>> -}
>> -return;
>> -case CRYPTO_ALG_TYPE_ABLKCIPHER:
>> -breq = ablkcipher_request_cast(engine->cur_req);
>> -if (engine->prepare_cipher_request) {
>> -ret = engine->prepare_cipher_request(engine, breq);
>> -if (ret) {
>> -dev_err(engine->dev, "failed to prepare 
>> request: %d\n",
>> -ret);
>> -goto req_err;
>> -}
>> -engine->cur_req_prepared = true;
>> -}
>> -ret = engine->cipher_one_request(engine, breq);
>> +enginectx = crypto_tfm_ctx(async_req->tfm);
>> +
>> +if (enginectx->op.prepare_request) {
>> +ret = enginectx->op.prepare_request(engine, async_req);
>>  if (ret) {
>> -dev_err(engine->dev, "failed to cipher one request from 
>> queue\n");
>> +dev_err(engine->dev, "failed to prepare request: %d\n",
>> +ret);
>>  goto req_err;
>>  }
>> -return;
>> -default:
>> -dev_err(engine->dev, "failed to prepare request of unknown 
>> type\n");
>> -return;
>> +engine->cur_req_prepared = true;
>> +}
>> +if (!enginectx->op.do_one_request) {
>> +dev_err(engine->dev, "failed to do request\n");
>> +ret = -EINVAL;
>> +goto req_err;
>> +}
>> +ret = enginectx->op.do_one_request(engine, async_req);
>> +if (ret) {
>> +dev_err(engine->dev, "Failed to do one request from queue: 
>> %d\n", ret);
>> +goto req_err;
>>  }
>> +return;
>>
>>req_err:
>> -switch (rtype) {
>> -case CRYPTO_ALG_TYPE_AHASH:
>> -hreq = ahash_request_cast(engine->cur_req);
>> -crypto_finalize_hash_request(engine, hreq, ret);
>> -break;
>> -case CRYPTO_ALG_TYPE_ABLKCIPHER:
>> -breq = ablkcipher_request_cast(engine->cur_req);
>> -crypto_finalize_cipher_request(engine, breq, ret);
>> -break;
>> -}
>> +crypto_finalize_request(engine, async_req, ret);
>>  return;
>>
>>out:
>> @@ -170,13 +141,12 @@ static void crypto_pump_work(struct 

Re: [PATCH 5/6] crypto: stm32-hash: convert to the new crypto engine API

2018-01-10 Thread Fabien DESSENNE
(adding my tested my)


On 10/01/18 15:24, Fabien DESSENNE wrote:
>
> On 03/01/18 21:11, Corentin Labbe wrote:
>> This patch convert the stm32-hash driver to the new crypto engine API.
>>
>> Signed-off-by: Corentin Labbe 

Tested-by: Fabien Dessenne 

>> ---
>>drivers/crypto/stm32/stm32-hash.c | 18 +-
>>1 file changed, 13 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/crypto/stm32/stm32-hash.c 
>> b/drivers/crypto/stm32/stm32-hash.c
>> index 4ca4a264a833..9790c2c936c7 100644
>> --- a/drivers/crypto/stm32/stm32-hash.c
>> +++ b/drivers/crypto/stm32/stm32-hash.c
>> @@ -122,6 +122,7 @@ enum stm32_hash_data_format {
>>#define HASH_DMA_THRESHOLD50
>>
>>struct stm32_hash_ctx {
>> +struct crypto_engine_reqctx enginectx;
>>  struct stm32_hash_dev   *hdev;
>>  unsigned long   flags;
>>
>> @@ -828,6 +829,11 @@ static int stm32_hash_hw_init(struct stm32_hash_dev 
>> *hdev,
>>  return 0;
>>}
>>
>> +static int stm32_hash_one_request(struct crypto_engine *engine,
>> +  void *areq);
> merge these two lines in a single one
>
>> +static int stm32_hash_prepare_req(struct crypto_engine *engine,
>> +  void *areq);
> merge these two lines in a single one
>
>> +
>>static int stm32_hash_handle_queue(struct stm32_hash_dev *hdev,
>> struct ahash_request *req)
>>{
>> @@ -835,8 +841,9 @@ static int stm32_hash_handle_queue(struct stm32_hash_dev 
>> *hdev,
>>}
>>
>>static int stm32_hash_prepare_req(struct crypto_engine *engine,
>> -  struct ahash_request *req)
>> +  void *areq)
> merge these two lines in a single one
>
>>{
>> +struct ahash_request *req = container_of(areq, struct ahash_request, 
>> base);
>   > 80 characters (CHECKPATCH)
>
>>  struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
>>  struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
>>  struct stm32_hash_request_ctx *rctx;
>> @@ -855,8 +862,9 @@ static int stm32_hash_prepare_req(struct crypto_engine 
>> *engine,
>>}
>>
>>static int stm32_hash_one_request(struct crypto_engine *engine,
>> -  struct ahash_request *req)
>> +  void *areq)
> merge these two lines in a single one
>
>>{
>> +struct ahash_request *req = container_of(areq, struct ahash_request, 
>> base);
>   > 80 characters (CHECKPATCH)
>
>>  struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
>>  struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
>>  struct stm32_hash_request_ctx *rctx;
>> @@ -1033,6 +1041,9 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm 
>> *tfm,
>>  if (algs_hmac_name)
>>  ctx->flags |= HASH_FLAGS_HMAC;
>>
>> +ctx->enginectx.op.do_one_request = stm32_hash_one_request;
>> +ctx->enginectx.op.prepare_request = stm32_hash_prepare_req;
>> +ctx->enginectx.op.unprepare_request = NULL;
>>  return 0;
>>}
>>
>> @@ -1493,9 +1504,6 @@ static int stm32_hash_probe(struct platform_device 
>> *pdev)
>>  goto err_engine;
>>  }
>>
>> -hdev->engine->prepare_hash_request = stm32_hash_prepare_req;
>> -hdev->engine->hash_one_request = stm32_hash_one_request;
>> -
>>  ret = crypto_engine_start(hdev->engine);
>>  if (ret)
>>  goto err_engine_start;


Re: [PATCH 5/6] crypto: stm32-hash: convert to the new crypto engine API

2018-01-10 Thread Fabien DESSENNE
(adding my tested my)


On 10/01/18 15:24, Fabien DESSENNE wrote:
>
> On 03/01/18 21:11, Corentin Labbe wrote:
>> This patch convert the stm32-hash driver to the new crypto engine API.
>>
>> Signed-off-by: Corentin Labbe 

Tested-by: Fabien Dessenne 

>> ---
>>drivers/crypto/stm32/stm32-hash.c | 18 +-
>>1 file changed, 13 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/crypto/stm32/stm32-hash.c 
>> b/drivers/crypto/stm32/stm32-hash.c
>> index 4ca4a264a833..9790c2c936c7 100644
>> --- a/drivers/crypto/stm32/stm32-hash.c
>> +++ b/drivers/crypto/stm32/stm32-hash.c
>> @@ -122,6 +122,7 @@ enum stm32_hash_data_format {
>>#define HASH_DMA_THRESHOLD50
>>
>>struct stm32_hash_ctx {
>> +struct crypto_engine_reqctx enginectx;
>>  struct stm32_hash_dev   *hdev;
>>  unsigned long   flags;
>>
>> @@ -828,6 +829,11 @@ static int stm32_hash_hw_init(struct stm32_hash_dev 
>> *hdev,
>>  return 0;
>>}
>>
>> +static int stm32_hash_one_request(struct crypto_engine *engine,
>> +  void *areq);
> merge these two lines in a single one
>
>> +static int stm32_hash_prepare_req(struct crypto_engine *engine,
>> +  void *areq);
> merge these two lines in a single one
>
>> +
>>static int stm32_hash_handle_queue(struct stm32_hash_dev *hdev,
>> struct ahash_request *req)
>>{
>> @@ -835,8 +841,9 @@ static int stm32_hash_handle_queue(struct stm32_hash_dev 
>> *hdev,
>>}
>>
>>static int stm32_hash_prepare_req(struct crypto_engine *engine,
>> -  struct ahash_request *req)
>> +  void *areq)
> merge these two lines in a single one
>
>>{
>> +struct ahash_request *req = container_of(areq, struct ahash_request, 
>> base);
>   > 80 characters (CHECKPATCH)
>
>>  struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
>>  struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
>>  struct stm32_hash_request_ctx *rctx;
>> @@ -855,8 +862,9 @@ static int stm32_hash_prepare_req(struct crypto_engine 
>> *engine,
>>}
>>
>>static int stm32_hash_one_request(struct crypto_engine *engine,
>> -  struct ahash_request *req)
>> +  void *areq)
> merge these two lines in a single one
>
>>{
>> +struct ahash_request *req = container_of(areq, struct ahash_request, 
>> base);
>   > 80 characters (CHECKPATCH)
>
>>  struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
>>  struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
>>  struct stm32_hash_request_ctx *rctx;
>> @@ -1033,6 +1041,9 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm 
>> *tfm,
>>  if (algs_hmac_name)
>>  ctx->flags |= HASH_FLAGS_HMAC;
>>
>> +ctx->enginectx.op.do_one_request = stm32_hash_one_request;
>> +ctx->enginectx.op.prepare_request = stm32_hash_prepare_req;
>> +ctx->enginectx.op.unprepare_request = NULL;
>>  return 0;
>>}
>>
>> @@ -1493,9 +1504,6 @@ static int stm32_hash_probe(struct platform_device 
>> *pdev)
>>  goto err_engine;
>>  }
>>
>> -hdev->engine->prepare_hash_request = stm32_hash_prepare_req;
>> -hdev->engine->hash_one_request = stm32_hash_one_request;
>> -
>>  ret = crypto_engine_start(hdev->engine);
>>  if (ret)
>>  goto err_engine_start;


Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Changwei Ge
On 2018/1/11 15:19, Gang He wrote:
> 
> 
> 

>> On 2018/1/11 12:31, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/11 11:33, Gang He wrote:
> Hi Changwei,
>
>

>> On 2018/1/11 10:07, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/10 18:14, Gang He wrote:
> Hi Changwei,
>
>

>> On 2018/1/10 17:05, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 Hi Gang,

 On 2017/12/14 13:16, Gang He wrote:
> As you know, ocfs2 has support trim the underlying disk via
> fstrim command. But there is a problem, ocfs2 is a shared disk
> cluster file system, if the user configures a scheduled fstrim
> job on each file system node, this will trigger multiple nodes
> trim a shared disk simultaneously, it is very wasteful for CPU
> and IO consumption, also might negatively affect the lifetime
> of poor-quality SSD devices.
> Then, we introduce a trimfs dlm lock to communicate with each
> other in this case, which will make only one fstrim command to
> do the trimming on a shared disk among the cluster, the fstrim
> commands from the other nodes should wait for the first fstrim
> to finish and returned success directly, to avoid running a the
> same trim on the shared disk again.
>
> Compare with first version, I change the fstrim commands' returned
> value and behavior in case which meets a fstrim command is running
> on a shared disk.
>
> Signed-off-by: Gang He 
> ---
> fs/ocfs2/alloc.c | 44 
> 
> 1 file changed, 44 insertions(+)
>
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index ab5105f..5c9c3e2 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
> struct
 fstrim_range *range)
>   struct buffer_head *gd_bh = NULL;
>   struct ocfs2_dinode *main_bm;
>   struct ocfs2_group_desc *gd = NULL;
> + struct ocfs2_trim_fs_info info, *pinfo = NULL;

 I think *pinfo* is not necessary.
>>> This pointer is necessary, since it can be NULL or non-NULL depend 
>>> on the
>> code logic.
>>
>> This point is OK for me.
>>
>>>
> 
>   start = range->start >> osb->s_clustersize_bits;
>   len = range->len >> osb->s_clustersize_bits;
> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
> struct
 fstrim_range *range)
> 
>   trace_ocfs2_trim_fs(start, len, minlen);
> 
> + ocfs2_trim_fs_lock_res_init(osb);
> + ret = ocfs2_trim_fs_lock(osb, NULL, 1);

 I don't get why try to lock here and if fails, acquire the same 
 lock again
 later but wait until granted.
>>> Please think about the user case, the patch is only used to handle 
>>> this
>> case.
>>> When the administer configures a fstrim schedule task on each node, 
>>> then
>> each node will trigger a fstrim on shared disks concurrently.
>>> In this case, we should avoid duplicated fstrim on a shared disk 
>>> since this
>> will waste CPU/IO resources and affect SSD lifetime sometimes.
>>
>> I'm not worrying about that trimfs will affect SSD's lifetime quite 
>> a lot,
>> since physical-logical address converting table resides in RAM while 
>> SSD is
>> working.
>> And that table won't be at a big scale. My point here is not 
>> affecting this
>> patch. Just a tip here.
> This depend on SSD firmware implementation, but for secure-trim, it 
> really
 possibly affect SSD lifetime.
>
>>> Firstly, we use try_lock to get fstrim dlm lock to identify if 
>>> there is any
>> other node which is doing fstrim on the disk.
>>> If not, this node is the first one, this node should do fstrim 
>>> operation on
>> the disk.
>>> If yes, this node is not the first one, this node should wait until 
>>> the
>> first node is done for fstrim operation, then return the result from 
>> DLM
>> lock's value.
>>>
 Can it just acquire the _trimfs_ lock as a 

Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Changwei Ge
On 2018/1/11 15:19, Gang He wrote:
> 
> 
> 

>> On 2018/1/11 12:31, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/11 11:33, Gang He wrote:
> Hi Changwei,
>
>

>> On 2018/1/11 10:07, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/10 18:14, Gang He wrote:
> Hi Changwei,
>
>

>> On 2018/1/10 17:05, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 Hi Gang,

 On 2017/12/14 13:16, Gang He wrote:
> As you know, ocfs2 has support trim the underlying disk via
> fstrim command. But there is a problem, ocfs2 is a shared disk
> cluster file system, if the user configures a scheduled fstrim
> job on each file system node, this will trigger multiple nodes
> trim a shared disk simultaneously, it is very wasteful for CPU
> and IO consumption, also might negatively affect the lifetime
> of poor-quality SSD devices.
> Then, we introduce a trimfs dlm lock to communicate with each
> other in this case, which will make only one fstrim command to
> do the trimming on a shared disk among the cluster, the fstrim
> commands from the other nodes should wait for the first fstrim
> to finish and returned success directly, to avoid running a the
> same trim on the shared disk again.
>
> Compare with first version, I change the fstrim commands' returned
> value and behavior in case which meets a fstrim command is running
> on a shared disk.
>
> Signed-off-by: Gang He 
> ---
> fs/ocfs2/alloc.c | 44 
> 
> 1 file changed, 44 insertions(+)
>
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index ab5105f..5c9c3e2 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
> struct
 fstrim_range *range)
>   struct buffer_head *gd_bh = NULL;
>   struct ocfs2_dinode *main_bm;
>   struct ocfs2_group_desc *gd = NULL;
> + struct ocfs2_trim_fs_info info, *pinfo = NULL;

 I think *pinfo* is not necessary.
>>> This pointer is necessary, since it can be NULL or non-NULL depend 
>>> on the
>> code logic.
>>
>> This point is OK for me.
>>
>>>
> 
>   start = range->start >> osb->s_clustersize_bits;
>   len = range->len >> osb->s_clustersize_bits;
> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
> struct
 fstrim_range *range)
> 
>   trace_ocfs2_trim_fs(start, len, minlen);
> 
> + ocfs2_trim_fs_lock_res_init(osb);
> + ret = ocfs2_trim_fs_lock(osb, NULL, 1);

 I don't get why try to lock here and if fails, acquire the same 
 lock again
 later but wait until granted.
>>> Please think about the user case, the patch is only used to handle 
>>> this
>> case.
>>> When the administer configures a fstrim schedule task on each node, 
>>> then
>> each node will trigger a fstrim on shared disks concurrently.
>>> In this case, we should avoid duplicated fstrim on a shared disk 
>>> since this
>> will waste CPU/IO resources and affect SSD lifetime sometimes.
>>
>> I'm not worrying about that trimfs will affect SSD's lifetime quite 
>> a lot,
>> since physical-logical address converting table resides in RAM while 
>> SSD is
>> working.
>> And that table won't be at a big scale. My point here is not 
>> affecting this
>> patch. Just a tip here.
> This depend on SSD firmware implementation, but for secure-trim, it 
> really
 possibly affect SSD lifetime.
>
>>> Firstly, we use try_lock to get fstrim dlm lock to identify if 
>>> there is any
>> other node which is doing fstrim on the disk.
>>> If not, this node is the first one, this node should do fstrim 
>>> operation on
>> the disk.
>>> If yes, this node is not the first one, this node should wait until 
>>> the
>> first node is done for fstrim operation, then return the result from 
>> DLM
>> lock's value.
>>>
 Can it just acquire the _trimfs_ lock as a blocking one 

Re: powersaving-related hangs on T460s

2018-01-10 Thread Meelis Roos
> I tried 4.15-git on my Thinkpad T460s laptop. It is working but I have 
> problems waking up the computer after it has been idle.
> 
> There should be no suspend (to keep network connections alive) when the 
> laptop is on AC power, even when the lid is closed. In dmesg, I have 
> seen no indication of suspend happening. It is configured to just lock 
> the screen when the lid is closed.
> 
> Normally, I have to press a key after opening the lid to unblank the 
> screen and get to password prompt. Usually this works but sometimes 
> there is no response - power LED is on that is all, holding down power 
> button is the only way out.
> 
> Sometimes it happens overnight, sometimes it is alive in the morning. It 
> almost never happens with short 5-15 minutes breaks but it can happen 
> for about hour long breaks. There is no reliable way to reproduce the 
> problem.

I seem to have found a better reproducer - when running on battery, it 
will hang after some minutes, with screen on. It just hangs.

-- 
Meelis Roos (mr...@linux.ee)


Re: powersaving-related hangs on T460s

2018-01-10 Thread Meelis Roos
> I tried 4.15-git on my Thinkpad T460s laptop. It is working but I have 
> problems waking up the computer after it has been idle.
> 
> There should be no suspend (to keep network connections alive) when the 
> laptop is on AC power, even when the lid is closed. In dmesg, I have 
> seen no indication of suspend happening. It is configured to just lock 
> the screen when the lid is closed.
> 
> Normally, I have to press a key after opening the lid to unblank the 
> screen and get to password prompt. Usually this works but sometimes 
> there is no response - power LED is on that is all, holding down power 
> button is the only way out.
> 
> Sometimes it happens overnight, sometimes it is alive in the morning. It 
> almost never happens with short 5-15 minutes breaks but it can happen 
> for about hour long breaks. There is no reliable way to reproduce the 
> problem.

I seem to have found a better reproducer - when running on battery, it 
will hang after some minutes, with screen on. It just hangs.

-- 
Meelis Roos (mr...@linux.ee)


Re: [PATCH v5 0/2] printk: Console owner and waiter logic cleanup

2018-01-10 Thread Sergey Senozhatsky
Hi Mathieu,

On (01/10/18 18:40), Mathieu Desnoyers wrote:
[..]
> 
> There appears to be two problems at hand. One is making sure a console
> buffer owner only flushes a bounded amount of data.

which, realistically, has quite little to do with the "and thus it
fixes the lockups". logbuf size is mutable, the number of consoles we
need to sequentially push the data to is mutable, the watchdog threshold
is mutable... if combination of first two mutable things produces the
result which makes the check based on the third mutable thing happy,
then it's just an accident. my 5 cents.

-ss


Re: [PATCH v5 0/2] printk: Console owner and waiter logic cleanup

2018-01-10 Thread Sergey Senozhatsky
Hi Mathieu,

On (01/10/18 18:40), Mathieu Desnoyers wrote:
[..]
> 
> There appears to be two problems at hand. One is making sure a console
> buffer owner only flushes a bounded amount of data.

which, realistically, has quite little to do with the "and thus it
fixes the lockups". logbuf size is mutable, the number of consoles we
need to sequentially push the data to is mutable, the watchdog threshold
is mutable... if combination of first two mutable things produces the
result which makes the check based on the third mutable thing happy,
then it's just an accident. my 5 cents.

-ss


Re: [PATCH linux dev-4.10 0/6] Add support PECI and PECI hwmon drivers

2018-01-10 Thread Greg KH
On Wed, Jan 10, 2018 at 01:46:34PM -0800, Jae Hyun Yoo wrote:
> On 1/10/2018 12:27 PM, Greg KH wrote:
> > On Wed, Jan 10, 2018 at 11:30:05AM -0800, Jae Hyun Yoo wrote:
> > > On 1/10/2018 11:17 AM, Greg KH wrote:
> > > > On Wed, Jan 10, 2018 at 11:14:34AM -0800, Jae Hyun Yoo wrote:
> > > > > On 1/10/2018 2:17 AM, Greg KH wrote:
> > > > > > On Tue, Jan 09, 2018 at 02:31:20PM -0800, Jae Hyun Yoo wrote:
> > > > > > > From: Jae Hyun Yoo 
> > > > > > > 
> > > > > > > Hello,
> > > > > > > 
> > > > > > > This patch set provides support for PECI of AST2400/2500 which 
> > > > > > > can give us PECI
> > > > > > > functionalities such as temperature monitoring, platform 
> > > > > > > manageability,
> > > > > > > processor diagnostics and failure analysis. Also provides generic 
> > > > > > > peci.h and
> > > > > > > peci_ioctl.h headers to provide compatibility to peci drivers 
> > > > > > > that can be
> > > > > > > implemented later e.g. Nuvoton's BMC SoC family.
> > > > > > 
> > > > > > What is the "dev-4.10" in the subject for?  4.10 is really old and
> > > > > > obsolete :(
> > > > > > 
> > > > > > thanks,
> > > > > > 
> > > > > > greg k-h
> > > > > > 
> > > > > 
> > > > > I made this patch set on top of the v4.10 which OpenBmc project is 
> > > > > currently
> > > > > using. I'll rebase this patch set onto the current kernel.org 
> > > > > mainline.
> > > > 
> > > > What is "OpenBmc", and why are they using an obsolete and insecure
> > > > kernel for their project?  That seems like a very foolish thing to do...
> > > > 
> > > > thanks,
> > > > 
> > > > greg k-h
> > > > 
> > > 
> > > OpenBmc is an open source project to create a highly extensible framework
> > > for BMC (Board Management Controller) software for data-center computer
> > > systems:
> > > https://github.com/openbmc
> > > 
> > > Its current mainline is v4.10 but it is being kept upgrading so it will be
> > > upgraded to the latest stable or long-term version soon.
> > 
> > Why hasn't it been updated in the year since 4.10 was released?  That's
> > a _very_ long time to be running on a totally insecure kernel, and no
> > new development should ever be done on old kernels, that's even crazier
> > (as we can't go back in time and accept patches for new features to old
> > releases...)
> > 
> 
> Thanks for your pointing it out and I totally agree with you. Actually, we
> are preparing 4.13 update for now and an another update will be followed up.
> As I answered above, I'll rebase this patch set onto the latest kernel.org
> mainline. Sorry for my misunderstanding of upstream process.

4.13?  Why that kernel?  It too is obsolete and insecure and
unsupported.

What keeps you all from just always tracking the latest tree from Linus?
What is in your tree that is not upstream that requires you to have a
kernel tree at all?

And if you do have out-of-tree code, why not use a process that makes it
trivial to update the base kernel version so that you can keep up to
date very easily?  (hint, just using 'git' is not a good way to do
this...)

thanks,

greg k-h


Re: [PATCH linux dev-4.10 0/6] Add support PECI and PECI hwmon drivers

2018-01-10 Thread Greg KH
On Wed, Jan 10, 2018 at 01:46:34PM -0800, Jae Hyun Yoo wrote:
> On 1/10/2018 12:27 PM, Greg KH wrote:
> > On Wed, Jan 10, 2018 at 11:30:05AM -0800, Jae Hyun Yoo wrote:
> > > On 1/10/2018 11:17 AM, Greg KH wrote:
> > > > On Wed, Jan 10, 2018 at 11:14:34AM -0800, Jae Hyun Yoo wrote:
> > > > > On 1/10/2018 2:17 AM, Greg KH wrote:
> > > > > > On Tue, Jan 09, 2018 at 02:31:20PM -0800, Jae Hyun Yoo wrote:
> > > > > > > From: Jae Hyun Yoo 
> > > > > > > 
> > > > > > > Hello,
> > > > > > > 
> > > > > > > This patch set provides support for PECI of AST2400/2500 which 
> > > > > > > can give us PECI
> > > > > > > functionalities such as temperature monitoring, platform 
> > > > > > > manageability,
> > > > > > > processor diagnostics and failure analysis. Also provides generic 
> > > > > > > peci.h and
> > > > > > > peci_ioctl.h headers to provide compatibility to peci drivers 
> > > > > > > that can be
> > > > > > > implemented later e.g. Nuvoton's BMC SoC family.
> > > > > > 
> > > > > > What is the "dev-4.10" in the subject for?  4.10 is really old and
> > > > > > obsolete :(
> > > > > > 
> > > > > > thanks,
> > > > > > 
> > > > > > greg k-h
> > > > > > 
> > > > > 
> > > > > I made this patch set on top of the v4.10 which OpenBmc project is 
> > > > > currently
> > > > > using. I'll rebase this patch set onto the current kernel.org 
> > > > > mainline.
> > > > 
> > > > What is "OpenBmc", and why are they using an obsolete and insecure
> > > > kernel for their project?  That seems like a very foolish thing to do...
> > > > 
> > > > thanks,
> > > > 
> > > > greg k-h
> > > > 
> > > 
> > > OpenBmc is an open source project to create a highly extensible framework
> > > for BMC (Board Management Controller) software for data-center computer
> > > systems:
> > > https://github.com/openbmc
> > > 
> > > Its current mainline is v4.10 but it is being kept upgrading so it will be
> > > upgraded to the latest stable or long-term version soon.
> > 
> > Why hasn't it been updated in the year since 4.10 was released?  That's
> > a _very_ long time to be running on a totally insecure kernel, and no
> > new development should ever be done on old kernels, that's even crazier
> > (as we can't go back in time and accept patches for new features to old
> > releases...)
> > 
> 
> Thanks for your pointing it out and I totally agree with you. Actually, we
> are preparing 4.13 update for now and an another update will be followed up.
> As I answered above, I'll rebase this patch set onto the latest kernel.org
> mainline. Sorry for my misunderstanding of upstream process.

4.13?  Why that kernel?  It too is obsolete and insecure and
unsupported.

What keeps you all from just always tracking the latest tree from Linus?
What is in your tree that is not upstream that requires you to have a
kernel tree at all?

And if you do have out-of-tree code, why not use a process that makes it
trivial to update the base kernel version so that you can keep up to
date very easily?  (hint, just using 'git' is not a good way to do
this...)

thanks,

greg k-h


[patch v8 3/3] platform/mellanox: mlxreg-hotplug: modify to use regmap intreface

2018-01-10 Thread Vadim Pasternak
It includes:
- restructuring  of mlxreg header file for unification of hotplug items
  definition;
- unification of hotplug items to allow any kind of item (power
  controller, fan eeprom, psu eeprom, asic health in common way);
- utilization of regmap interface to allow independency of underlying
  hardware. It allows to support hotplug event functionality over
  programmable devices logic, when these devices can be attached to
  different interfaces types, like I2C, LPC, SPI.

Signed-off-by: Vadim Pasternak 
Acked-by: Andy Shevchenko 
---
v7->v8
v6->v7
 Fixes added by Vadim:
 - Remove include  in mlxreg-hotplug.c in this patch.
v5->v6:
 Fixes added by Vadim:
 - rename mlxreg_core_led_platform_data to common name
   mlxreg_core_platform_data;
 - add cell_low and mask_low fields to
   mlxreg_core_hotplug_platform_data for low aggregation interrupt
   registers and check for these fields in mlxreg_hotplug_set_irq and
   mlxreg_hotplug_unset_irq;
v4->v5:
 Comments pointed out by Andy:
 - use suffix OFFSET instead of ADDR for aggregation registers;
 - return back MACROS;
 - rearrange mlxreg_hotplug_attr_init routine;
---
 drivers/platform/mellanox/Kconfig  |   1 +
 drivers/platform/mellanox/mlxreg-hotplug.c | 613 +
 drivers/platform/x86/mlx-platform.c| 231 ---
 include/linux/platform_data/mlxreg.h   | 126 --
 4 files changed, 638 insertions(+), 333 deletions(-)

diff --git a/drivers/platform/mellanox/Kconfig 
b/drivers/platform/mellanox/Kconfig
index 0267e1d..591bccd 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -16,6 +16,7 @@ if MELLANOX_PLATFORM
 
 config MLXREG_HOTPLUG
tristate "Mellanox platform hotplug driver support"
+   depends on REGMAP
depends on HWMON
depends on I2C
---help---
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c 
b/drivers/platform/mellanox/mlxreg-hotplug.c
index 556e612..9bbaa8c 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -37,92 +37,88 @@
 #include 
 #include 
 #include 
-#include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 
-/* Offset of event and mask registers from status register */
+/* Offset of event and mask registers from status register. */
 #define MLXREG_HOTPLUG_EVENT_OFF   1
-#define MLXREG_HOTPLUG_MASK_OFF2
+#define MLXREG_HOTPLUG_MASK_OFF2
 #define MLXREG_HOTPLUG_AGGR_MASK_OFF   1
 
-#define MLXREG_HOTPLUG_ATTRS_NUM   8
+/* ASIC health parameters. */
+#define MLXREG_HOTPLUG_HEALTH_MASK 0x02
+#define MLXREG_HOTPLUG_RST_CNTR3
 
-/**
- * enum mlxreg_hotplug_attr_type - sysfs attributes for hotplug events:
- * @MLXREG_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute;
- * @MLXREG_HOTPLUG_ATTR_TYPE_PWR: power cable attribute;
- * @MLXREG_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute;
- */
-enum mlxreg_hotplug_attr_type {
-   MLXREG_HOTPLUG_ATTR_TYPE_PSU,
-   MLXREG_HOTPLUG_ATTR_TYPE_PWR,
-   MLXREG_HOTPLUG_ATTR_TYPE_FAN,
-};
+#define MLXREG_HOTPLUG_ATTRS_MAX   24
 
 /**
  * struct mlxreg_hotplug_priv_data - platform private data:
- * @irq: platform interrupt number;
+ * @irq: platform device interrupt number;
  * @pdev: platform device;
  * @plat: platform data;
+ * @dwork: delayed work template;
+ * @lock: spin lock;
  * @hwmon: hwmon device;
  * @mlxreg_hotplug_attr: sysfs attributes array;
  * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
  * @group: sysfs attribute group;
  * @groups: list of sysfs attribute group for hwmon registration;
- * @dwork: delayed work template;
- * @lock: spin lock;
+ * @cell: location of top aggregation interrupt register;
+ * @mask: top aggregation interrupt common mask;
  * @aggr_cache: last value of aggregation register status;
- * @psu_cache: last value of PSU register status;
- * @pwr_cache: last value of power register status;
- * @fan_cache: last value of FAN register status;
  */
 struct mlxreg_hotplug_priv_data {
int irq;
+   struct device *dev;
struct platform_device *pdev;
struct mlxreg_hotplug_platform_data *plat;
+   struct regmap *regmap;
+   struct delayed_work dwork_irq;
+   struct delayed_work dwork;
+   spinlock_t lock; /* sync with interrupt */
struct device *hwmon;
-   struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_NUM + 1];
+   struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
struct sensor_device_attribute_2
-   mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_NUM];
+   mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX];
struct attribute_group group;
const struct attribute_group *groups[2];
-   struct delayed_work dwork;
-   spinlock_t lock;
-   u8 aggr_cache;
-   u8 psu_cache;
-   u8 pwr_cache;

[patch v8 3/3] platform/mellanox: mlxreg-hotplug: modify to use regmap intreface

2018-01-10 Thread Vadim Pasternak
It includes:
- restructuring  of mlxreg header file for unification of hotplug items
  definition;
- unification of hotplug items to allow any kind of item (power
  controller, fan eeprom, psu eeprom, asic health in common way);
- utilization of regmap interface to allow independency of underlying
  hardware. It allows to support hotplug event functionality over
  programmable devices logic, when these devices can be attached to
  different interfaces types, like I2C, LPC, SPI.

Signed-off-by: Vadim Pasternak 
Acked-by: Andy Shevchenko 
---
v7->v8
v6->v7
 Fixes added by Vadim:
 - Remove include  in mlxreg-hotplug.c in this patch.
v5->v6:
 Fixes added by Vadim:
 - rename mlxreg_core_led_platform_data to common name
   mlxreg_core_platform_data;
 - add cell_low and mask_low fields to
   mlxreg_core_hotplug_platform_data for low aggregation interrupt
   registers and check for these fields in mlxreg_hotplug_set_irq and
   mlxreg_hotplug_unset_irq;
v4->v5:
 Comments pointed out by Andy:
 - use suffix OFFSET instead of ADDR for aggregation registers;
 - return back MACROS;
 - rearrange mlxreg_hotplug_attr_init routine;
---
 drivers/platform/mellanox/Kconfig  |   1 +
 drivers/platform/mellanox/mlxreg-hotplug.c | 613 +
 drivers/platform/x86/mlx-platform.c| 231 ---
 include/linux/platform_data/mlxreg.h   | 126 --
 4 files changed, 638 insertions(+), 333 deletions(-)

diff --git a/drivers/platform/mellanox/Kconfig 
b/drivers/platform/mellanox/Kconfig
index 0267e1d..591bccd 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -16,6 +16,7 @@ if MELLANOX_PLATFORM
 
 config MLXREG_HOTPLUG
tristate "Mellanox platform hotplug driver support"
+   depends on REGMAP
depends on HWMON
depends on I2C
---help---
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c 
b/drivers/platform/mellanox/mlxreg-hotplug.c
index 556e612..9bbaa8c 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -37,92 +37,88 @@
 #include 
 #include 
 #include 
-#include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 
-/* Offset of event and mask registers from status register */
+/* Offset of event and mask registers from status register. */
 #define MLXREG_HOTPLUG_EVENT_OFF   1
-#define MLXREG_HOTPLUG_MASK_OFF2
+#define MLXREG_HOTPLUG_MASK_OFF2
 #define MLXREG_HOTPLUG_AGGR_MASK_OFF   1
 
-#define MLXREG_HOTPLUG_ATTRS_NUM   8
+/* ASIC health parameters. */
+#define MLXREG_HOTPLUG_HEALTH_MASK 0x02
+#define MLXREG_HOTPLUG_RST_CNTR3
 
-/**
- * enum mlxreg_hotplug_attr_type - sysfs attributes for hotplug events:
- * @MLXREG_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute;
- * @MLXREG_HOTPLUG_ATTR_TYPE_PWR: power cable attribute;
- * @MLXREG_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute;
- */
-enum mlxreg_hotplug_attr_type {
-   MLXREG_HOTPLUG_ATTR_TYPE_PSU,
-   MLXREG_HOTPLUG_ATTR_TYPE_PWR,
-   MLXREG_HOTPLUG_ATTR_TYPE_FAN,
-};
+#define MLXREG_HOTPLUG_ATTRS_MAX   24
 
 /**
  * struct mlxreg_hotplug_priv_data - platform private data:
- * @irq: platform interrupt number;
+ * @irq: platform device interrupt number;
  * @pdev: platform device;
  * @plat: platform data;
+ * @dwork: delayed work template;
+ * @lock: spin lock;
  * @hwmon: hwmon device;
  * @mlxreg_hotplug_attr: sysfs attributes array;
  * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
  * @group: sysfs attribute group;
  * @groups: list of sysfs attribute group for hwmon registration;
- * @dwork: delayed work template;
- * @lock: spin lock;
+ * @cell: location of top aggregation interrupt register;
+ * @mask: top aggregation interrupt common mask;
  * @aggr_cache: last value of aggregation register status;
- * @psu_cache: last value of PSU register status;
- * @pwr_cache: last value of power register status;
- * @fan_cache: last value of FAN register status;
  */
 struct mlxreg_hotplug_priv_data {
int irq;
+   struct device *dev;
struct platform_device *pdev;
struct mlxreg_hotplug_platform_data *plat;
+   struct regmap *regmap;
+   struct delayed_work dwork_irq;
+   struct delayed_work dwork;
+   spinlock_t lock; /* sync with interrupt */
struct device *hwmon;
-   struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_NUM + 1];
+   struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
struct sensor_device_attribute_2
-   mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_NUM];
+   mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX];
struct attribute_group group;
const struct attribute_group *groups[2];
-   struct delayed_work dwork;
-   spinlock_t lock;
-   u8 aggr_cache;
-   u8 psu_cache;
-   u8 pwr_cache;
-   u8 fan_cache;
+   u32 cell;
+   

[patch v8 1/3] platform/x86: move Mellanox hardware platform hotplug driver to platform/mellanox

2018-01-10 Thread Vadim Pasternak
It moves drivers/platform/x86/mlxcpld-hotplug.c to
drivers/platform/mellanox/mlxreg-hotplug.c and
include/linux/platform_data/mlxcpld-hotplug.h to
include/linux/platform_data/mlxreg.h for making hotplug driver usable for
the different machine architectures.

Signed-off-by: Vadim Pasternak 
Acked-by: Andy Shevchenko 
---
v7->v8:
v6->v7:
 Fixes added by Vadim:
 - remove dependency on X86_64 to allow also X86 architecture;
v5->v6:
 Fixes added by Vadim:
 - add SPD license record to Kconfig and Makefile;
v4->v5:
 Comments pointed out by Andy:
 - arrange MAINTAINERS in correct alphabetic order;
v3->v4:
 Comments pointed out by Darren:
 - Refactor the patches to provide the changes in patchset in incremental
   order;
 - Modify MAINTAINERS records;
 - Use git-mv for the replaced files;
  Commnets pointed out by Colin:
 - Make structures mlxplat_dev and mlxplat_hotplug static;
---
 MAINTAINERS|   7 +-
 drivers/platform/Kconfig   |   2 +
 drivers/platform/Makefile  |   1 +
 drivers/platform/mellanox/Kconfig  |  25 +++
 drivers/platform/mellanox/Makefile |   6 +
 .../mlxreg-hotplug.c}  | 223 ++---
 drivers/platform/x86/Kconfig   |   9 -
 drivers/platform/x86/Makefile  |   1 -
 drivers/platform/x86/mlx-platform.c|  18 +-
 .../platform_data/{mlxcpld-hotplug.h => mlxreg.h}  |  25 ++-
 10 files changed, 170 insertions(+), 147 deletions(-)
 create mode 100644 drivers/platform/mellanox/Kconfig
 create mode 100644 drivers/platform/mellanox/Makefile
 rename drivers/platform/{x86/mlxcpld-hotplug.c => mellanox/mlxreg-hotplug.c} 
(65%)
 rename include/linux/platform_data/{mlxcpld-hotplug.h => mlxreg.h} (84%)

diff --git a/MAINTAINERS b/MAINTAINERS
index bc4d776..c07e114 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8860,12 +8860,13 @@ W:  http://www.mellanox.com
 Q: http://patchwork.ozlabs.org/project/netdev/list/
 F: drivers/net/ethernet/mellanox/mlxfw/
 
-MELLANOX MLX CPLD HOTPLUG DRIVER
+MELLANOX HARDWARE PLATFORM SUPPORT
+M: Andy Shevchenko 
+M: Darren Hart 
 M: Vadim Pasternak 
 L: platform-driver-...@vger.kernel.org
 S: Supported
-F: drivers/platform/x86/mlxcpld-hotplug.c
-F: include/linux/platform_data/mlxcpld-hotplug.h
+F: drivers/platform/mellanox/
 
 MELLANOX MLX4 core VPI driver
 M: Tariq Toukan 
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index c11db8b..d4c2e42 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -8,3 +8,5 @@ endif
 source "drivers/platform/goldfish/Kconfig"
 
 source "drivers/platform/chrome/Kconfig"
+
+source "drivers/platform/mellanox/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index d3a6630..4b2ce58 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_X86)  += x86/
+obj-$(CONFIG_MELLANOX_PLATFORM)+= mellanox/
 obj-$(CONFIG_MIPS) += mips/
 obj-$(CONFIG_OLPC) += olpc/
 obj-$(CONFIG_GOLDFISH) += goldfish/
diff --git a/drivers/platform/mellanox/Kconfig 
b/drivers/platform/mellanox/Kconfig
new file mode 100644
index 000..d735292
--- /dev/null
+++ b/drivers/platform/mellanox/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Platform support for Mellanox hardware
+#
+
+menuconfig MELLANOX_PLATFORM
+   bool "Platform support for Mellanox hardware"
+   depends on X86 || COMPILE_TEST
+   ---help---
+ Say Y here to get to see options for platform support for
+ Mellanox systems. This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and 
disabled.
+
+if MELLANOX_PLATFORM
+
+config MLXREG_HOTPLUG
+   tristate "Mellanox platform hotplug driver support"
+   depends on HWMON
+   depends on I2C
+   ---help---
+ This driver handles hot-plug events for the power suppliers, power
+ cables and fans on the wide range Mellanox IB and Ethernet systems.
+
+endif # MELLANOX_PLATFORM
diff --git a/drivers/platform/mellanox/Makefile 
b/drivers/platform/mellanox/Makefile
new file mode 100644
index 000..7c8385e
--- /dev/null
+++ b/drivers/platform/mellanox/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for linux/drivers/platform/mellanox
+# Mellanox Platform-Specific Drivers
+#
+obj-$(CONFIG_MLXREG_HOTPLUG)   += mlxreg-hotplug.o
diff --git a/drivers/platform/x86/mlxcpld-hotplug.c 
b/drivers/platform/mellanox/mlxreg-hotplug.c
similarity index 65%
rename from drivers/platform/x86/mlxcpld-hotplug.c
rename to drivers/platform/mellanox/mlxreg-hotplug.c
index aff3686..2866c76 100644
--- 

[patch v8 1/3] platform/x86: move Mellanox hardware platform hotplug driver to platform/mellanox

2018-01-10 Thread Vadim Pasternak
It moves drivers/platform/x86/mlxcpld-hotplug.c to
drivers/platform/mellanox/mlxreg-hotplug.c and
include/linux/platform_data/mlxcpld-hotplug.h to
include/linux/platform_data/mlxreg.h for making hotplug driver usable for
the different machine architectures.

Signed-off-by: Vadim Pasternak 
Acked-by: Andy Shevchenko 
---
v7->v8:
v6->v7:
 Fixes added by Vadim:
 - remove dependency on X86_64 to allow also X86 architecture;
v5->v6:
 Fixes added by Vadim:
 - add SPD license record to Kconfig and Makefile;
v4->v5:
 Comments pointed out by Andy:
 - arrange MAINTAINERS in correct alphabetic order;
v3->v4:
 Comments pointed out by Darren:
 - Refactor the patches to provide the changes in patchset in incremental
   order;
 - Modify MAINTAINERS records;
 - Use git-mv for the replaced files;
  Commnets pointed out by Colin:
 - Make structures mlxplat_dev and mlxplat_hotplug static;
---
 MAINTAINERS|   7 +-
 drivers/platform/Kconfig   |   2 +
 drivers/platform/Makefile  |   1 +
 drivers/platform/mellanox/Kconfig  |  25 +++
 drivers/platform/mellanox/Makefile |   6 +
 .../mlxreg-hotplug.c}  | 223 ++---
 drivers/platform/x86/Kconfig   |   9 -
 drivers/platform/x86/Makefile  |   1 -
 drivers/platform/x86/mlx-platform.c|  18 +-
 .../platform_data/{mlxcpld-hotplug.h => mlxreg.h}  |  25 ++-
 10 files changed, 170 insertions(+), 147 deletions(-)
 create mode 100644 drivers/platform/mellanox/Kconfig
 create mode 100644 drivers/platform/mellanox/Makefile
 rename drivers/platform/{x86/mlxcpld-hotplug.c => mellanox/mlxreg-hotplug.c} 
(65%)
 rename include/linux/platform_data/{mlxcpld-hotplug.h => mlxreg.h} (84%)

diff --git a/MAINTAINERS b/MAINTAINERS
index bc4d776..c07e114 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8860,12 +8860,13 @@ W:  http://www.mellanox.com
 Q: http://patchwork.ozlabs.org/project/netdev/list/
 F: drivers/net/ethernet/mellanox/mlxfw/
 
-MELLANOX MLX CPLD HOTPLUG DRIVER
+MELLANOX HARDWARE PLATFORM SUPPORT
+M: Andy Shevchenko 
+M: Darren Hart 
 M: Vadim Pasternak 
 L: platform-driver-...@vger.kernel.org
 S: Supported
-F: drivers/platform/x86/mlxcpld-hotplug.c
-F: include/linux/platform_data/mlxcpld-hotplug.h
+F: drivers/platform/mellanox/
 
 MELLANOX MLX4 core VPI driver
 M: Tariq Toukan 
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index c11db8b..d4c2e42 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -8,3 +8,5 @@ endif
 source "drivers/platform/goldfish/Kconfig"
 
 source "drivers/platform/chrome/Kconfig"
+
+source "drivers/platform/mellanox/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index d3a6630..4b2ce58 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_X86)  += x86/
+obj-$(CONFIG_MELLANOX_PLATFORM)+= mellanox/
 obj-$(CONFIG_MIPS) += mips/
 obj-$(CONFIG_OLPC) += olpc/
 obj-$(CONFIG_GOLDFISH) += goldfish/
diff --git a/drivers/platform/mellanox/Kconfig 
b/drivers/platform/mellanox/Kconfig
new file mode 100644
index 000..d735292
--- /dev/null
+++ b/drivers/platform/mellanox/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Platform support for Mellanox hardware
+#
+
+menuconfig MELLANOX_PLATFORM
+   bool "Platform support for Mellanox hardware"
+   depends on X86 || COMPILE_TEST
+   ---help---
+ Say Y here to get to see options for platform support for
+ Mellanox systems. This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and 
disabled.
+
+if MELLANOX_PLATFORM
+
+config MLXREG_HOTPLUG
+   tristate "Mellanox platform hotplug driver support"
+   depends on HWMON
+   depends on I2C
+   ---help---
+ This driver handles hot-plug events for the power suppliers, power
+ cables and fans on the wide range Mellanox IB and Ethernet systems.
+
+endif # MELLANOX_PLATFORM
diff --git a/drivers/platform/mellanox/Makefile 
b/drivers/platform/mellanox/Makefile
new file mode 100644
index 000..7c8385e
--- /dev/null
+++ b/drivers/platform/mellanox/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for linux/drivers/platform/mellanox
+# Mellanox Platform-Specific Drivers
+#
+obj-$(CONFIG_MLXREG_HOTPLUG)   += mlxreg-hotplug.o
diff --git a/drivers/platform/x86/mlxcpld-hotplug.c 
b/drivers/platform/mellanox/mlxreg-hotplug.c
similarity index 65%
rename from drivers/platform/x86/mlxcpld-hotplug.c
rename to drivers/platform/mellanox/mlxreg-hotplug.c
index aff3686..2866c76 100644
--- a/drivers/platform/x86/mlxcpld-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -1,7 +1,6 @@
 /*
- * 

[patch v8 2/3] platform/mellanox: mlxreg-hotplug: allow driver for ARM architecture

2018-01-10 Thread Vadim Pasternak
It allows driver to run on x86 and ARM architecture based systems.
Also some unnecessary includes are removed.

Signed-off-by: Vadim Pasternak 
Acked-by: Andy Shevchenko 
---
v7->v8
 Fixes added by Vadim:
 - Drop routines using of_update_property. It causes  Kbuild error for
   ia64 arch during on modpost, since of_update_property is not exported.
   The intension of these routines was the dynamic enabling and disabling
   of the device tree node, when relevant signal is received. Such node
   has been supposed to set with the property disabled in DTS, and
   changing property by using of_update_property just flips the device.
   It was OK for arm and sparc, but not for ia64.
v6->v7
 Fixes added by Vadim:
 - Dont remove include  in mlxreg-hotplug.c to avoid Kbuild
   errors. Make this change in patch 3/3.
v5->v6:
v4->v5:
 Comments pointed out by Andy:
 - remove unnessecary logic in Kconfig;
 - remove !COMPILE_TEST in mlxreg-hotplug;
---
 drivers/platform/mellanox/Kconfig  |  2 +-
 drivers/platform/mellanox/mlxreg-hotplug.c | 70 +-
 drivers/platform/x86/mlx-platform.c| 16 +++
 include/linux/platform_data/mlxreg.h   |  6 ++-
 4 files changed, 44 insertions(+), 50 deletions(-)

diff --git a/drivers/platform/mellanox/Kconfig 
b/drivers/platform/mellanox/Kconfig
index d735292..0267e1d 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -5,7 +5,7 @@
 
 menuconfig MELLANOX_PLATFORM
bool "Platform support for Mellanox hardware"
-   depends on X86 || COMPILE_TEST
+   depends on X86 || ARM || COMPILE_TEST
---help---
  Say Y here to get to see options for platform support for
  Mellanox systems. This option alone does not add any kernel code.
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c 
b/drivers/platform/mellanox/mlxreg-hotplug.c
index 2866c76..556e612 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -41,8 +41,6 @@
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 
 /* Offset of event and mask registers from status register */
@@ -99,6 +97,35 @@ struct mlxreg_hotplug_priv_data {
u8 fan_cache;
 };
 
+static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_device *data)
+{
+   data->adapter = i2c_get_adapter(data->nr);
+   if (!data->adapter)
+   return -EFAULT;
+
+   data->client = i2c_new_device(data->adapter, >brdinfo);
+   if (!data->client) {
+   i2c_put_adapter(data->adapter);
+   data->adapter = NULL;
+   return -EFAULT;
+   }
+
+   return 0;
+}
+
+static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *data)
+{
+   if (data->client) {
+   i2c_unregister_device(data->client);
+   data->client = NULL;
+   }
+
+   if (data->adapter) {
+   i2c_put_adapter(data->adapter);
+   data->adapter = NULL;
+   }
+}
+
 static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -184,41 +211,6 @@ static int mlxreg_hotplug_attr_init(struct 
mlxreg_hotplug_priv_data *priv)
return 0;
 }
 
-static int mlxreg_hotplug_device_create(struct device *dev,
-   struct mlxreg_hotplug_device *item)
-{
-   item->adapter = i2c_get_adapter(item->bus);
-   if (!item->adapter) {
-   dev_err(dev, "Failed to get adapter for bus %d\n",
-   item->bus);
-   return -EFAULT;
-   }
-
-   item->client = i2c_new_device(item->adapter, >brdinfo);
-   if (!item->client) {
-   dev_err(dev, "Failed to create client %s at bus %d at addr 
0x%02x\n",
-   item->brdinfo.type, item->bus, item->brdinfo.addr);
-   i2c_put_adapter(item->adapter);
-   item->adapter = NULL;
-   return -EFAULT;
-   }
-
-   return 0;
-}
-
-static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *item)
-{
-   if (item->client) {
-   i2c_unregister_device(item->client);
-   item->client = NULL;
-   }
-
-   if (item->adapter) {
-   i2c_put_adapter(item->adapter);
-   item->adapter = NULL;
-   }
-}
-
 static inline void
 mlxreg_hotplug_work_helper(struct device *dev,
   struct mlxreg_hotplug_device *item, u8 is_inverse,
@@ -252,10 +244,10 @@ mlxreg_hotplug_work_helper(struct device *dev,
if (is_inverse)
mlxreg_hotplug_device_destroy(item + bit);
else
-   mlxreg_hotplug_device_create(dev, item + bit);
+   

[patch v8 2/3] platform/mellanox: mlxreg-hotplug: allow driver for ARM architecture

2018-01-10 Thread Vadim Pasternak
It allows driver to run on x86 and ARM architecture based systems.
Also some unnecessary includes are removed.

Signed-off-by: Vadim Pasternak 
Acked-by: Andy Shevchenko 
---
v7->v8
 Fixes added by Vadim:
 - Drop routines using of_update_property. It causes  Kbuild error for
   ia64 arch during on modpost, since of_update_property is not exported.
   The intension of these routines was the dynamic enabling and disabling
   of the device tree node, when relevant signal is received. Such node
   has been supposed to set with the property disabled in DTS, and
   changing property by using of_update_property just flips the device.
   It was OK for arm and sparc, but not for ia64.
v6->v7
 Fixes added by Vadim:
 - Dont remove include  in mlxreg-hotplug.c to avoid Kbuild
   errors. Make this change in patch 3/3.
v5->v6:
v4->v5:
 Comments pointed out by Andy:
 - remove unnessecary logic in Kconfig;
 - remove !COMPILE_TEST in mlxreg-hotplug;
---
 drivers/platform/mellanox/Kconfig  |  2 +-
 drivers/platform/mellanox/mlxreg-hotplug.c | 70 +-
 drivers/platform/x86/mlx-platform.c| 16 +++
 include/linux/platform_data/mlxreg.h   |  6 ++-
 4 files changed, 44 insertions(+), 50 deletions(-)

diff --git a/drivers/platform/mellanox/Kconfig 
b/drivers/platform/mellanox/Kconfig
index d735292..0267e1d 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -5,7 +5,7 @@
 
 menuconfig MELLANOX_PLATFORM
bool "Platform support for Mellanox hardware"
-   depends on X86 || COMPILE_TEST
+   depends on X86 || ARM || COMPILE_TEST
---help---
  Say Y here to get to see options for platform support for
  Mellanox systems. This option alone does not add any kernel code.
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c 
b/drivers/platform/mellanox/mlxreg-hotplug.c
index 2866c76..556e612 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -41,8 +41,6 @@
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 
 /* Offset of event and mask registers from status register */
@@ -99,6 +97,35 @@ struct mlxreg_hotplug_priv_data {
u8 fan_cache;
 };
 
+static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_device *data)
+{
+   data->adapter = i2c_get_adapter(data->nr);
+   if (!data->adapter)
+   return -EFAULT;
+
+   data->client = i2c_new_device(data->adapter, >brdinfo);
+   if (!data->client) {
+   i2c_put_adapter(data->adapter);
+   data->adapter = NULL;
+   return -EFAULT;
+   }
+
+   return 0;
+}
+
+static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *data)
+{
+   if (data->client) {
+   i2c_unregister_device(data->client);
+   data->client = NULL;
+   }
+
+   if (data->adapter) {
+   i2c_put_adapter(data->adapter);
+   data->adapter = NULL;
+   }
+}
+
 static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -184,41 +211,6 @@ static int mlxreg_hotplug_attr_init(struct 
mlxreg_hotplug_priv_data *priv)
return 0;
 }
 
-static int mlxreg_hotplug_device_create(struct device *dev,
-   struct mlxreg_hotplug_device *item)
-{
-   item->adapter = i2c_get_adapter(item->bus);
-   if (!item->adapter) {
-   dev_err(dev, "Failed to get adapter for bus %d\n",
-   item->bus);
-   return -EFAULT;
-   }
-
-   item->client = i2c_new_device(item->adapter, >brdinfo);
-   if (!item->client) {
-   dev_err(dev, "Failed to create client %s at bus %d at addr 
0x%02x\n",
-   item->brdinfo.type, item->bus, item->brdinfo.addr);
-   i2c_put_adapter(item->adapter);
-   item->adapter = NULL;
-   return -EFAULT;
-   }
-
-   return 0;
-}
-
-static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *item)
-{
-   if (item->client) {
-   i2c_unregister_device(item->client);
-   item->client = NULL;
-   }
-
-   if (item->adapter) {
-   i2c_put_adapter(item->adapter);
-   item->adapter = NULL;
-   }
-}
-
 static inline void
 mlxreg_hotplug_work_helper(struct device *dev,
   struct mlxreg_hotplug_device *item, u8 is_inverse,
@@ -252,10 +244,10 @@ mlxreg_hotplug_work_helper(struct device *dev,
if (is_inverse)
mlxreg_hotplug_device_destroy(item + bit);
else
-   mlxreg_hotplug_device_create(dev, item + bit);
+   mlxreg_hotplug_device_create(item + bit);
} else {

[patch v8 0/3] drivers/platform: replace module x86/mlxcpld-hotplug with mellanox/mlxreg-hotplug

2018-01-10 Thread Vadim Pasternak
The patchset:
 - replaces modules include/linux/platform_data/mlxcpld-hotplug.h and
   drivers/platform/x86/mlxcpld-hotplug.c with the modules
   include/linux/platform_data/mlxreg.h and
   drivers/platform/mellanox/mlxreg-hotplug.c;
   relevant Makefile and Kconfig are updated;
 - modifies Mellanox hotplug driver for making it architecture
   independent. Drivers has been tested for x86 and ARM based systems.
 - introduces regmap interface for mlxreg-hotplug driver to allow hotplug
   event functionality over programmable devices logic, when these devices
   can be attached to different interfaces types, like I2C, LPC, SPI;
   driver drivers/platform/x86/mlx-platform.c is updated according to new
   interface.

Vadim Pasternak (3):
  platform/x86: move Mellanox hardware platform hotplug driver to
platform/mellanox
  platform/mellanox: mlxreg-hotplug: allow driver for ARM architecture
  platform/mellanox: mlxreg-hotplug: modify to use regmap intreface

 MAINTAINERS   |   7 +-
 drivers/platform/Kconfig  |   2 +
 drivers/platform/Makefile |   1 +
 drivers/platform/mellanox/Kconfig |  26 ++
 drivers/platform/mellanox/Makefile|   6 +
 drivers/platform/mellanox/mlxreg-hotplug.c| 633 ++
 drivers/platform/x86/Kconfig  |   9 -
 drivers/platform/x86/Makefile |   1 -
 drivers/platform/x86/mlx-platform.c   | 237 +++---
 drivers/platform/x86/mlxcpld-hotplug.c| 515 -
 include/linux/platform_data/mlxcpld-hotplug.h |  99 
 include/linux/platform_data/mlxreg.h  | 144 ++
 12 files changed, 1001 insertions(+), 679 deletions(-)
 create mode 100644 drivers/platform/mellanox/Kconfig
 create mode 100644 drivers/platform/mellanox/Makefile
 create mode 100644 drivers/platform/mellanox/mlxreg-hotplug.c
 delete mode 100644 drivers/platform/x86/mlxcpld-hotplug.c
 delete mode 100644 include/linux/platform_data/mlxcpld-hotplug.h
 create mode 100644 include/linux/platform_data/mlxreg.h

-- 
2.1.4



[patch v8 0/3] drivers/platform: replace module x86/mlxcpld-hotplug with mellanox/mlxreg-hotplug

2018-01-10 Thread Vadim Pasternak
The patchset:
 - replaces modules include/linux/platform_data/mlxcpld-hotplug.h and
   drivers/platform/x86/mlxcpld-hotplug.c with the modules
   include/linux/platform_data/mlxreg.h and
   drivers/platform/mellanox/mlxreg-hotplug.c;
   relevant Makefile and Kconfig are updated;
 - modifies Mellanox hotplug driver for making it architecture
   independent. Drivers has been tested for x86 and ARM based systems.
 - introduces regmap interface for mlxreg-hotplug driver to allow hotplug
   event functionality over programmable devices logic, when these devices
   can be attached to different interfaces types, like I2C, LPC, SPI;
   driver drivers/platform/x86/mlx-platform.c is updated according to new
   interface.

Vadim Pasternak (3):
  platform/x86: move Mellanox hardware platform hotplug driver to
platform/mellanox
  platform/mellanox: mlxreg-hotplug: allow driver for ARM architecture
  platform/mellanox: mlxreg-hotplug: modify to use regmap intreface

 MAINTAINERS   |   7 +-
 drivers/platform/Kconfig  |   2 +
 drivers/platform/Makefile |   1 +
 drivers/platform/mellanox/Kconfig |  26 ++
 drivers/platform/mellanox/Makefile|   6 +
 drivers/platform/mellanox/mlxreg-hotplug.c| 633 ++
 drivers/platform/x86/Kconfig  |   9 -
 drivers/platform/x86/Makefile |   1 -
 drivers/platform/x86/mlx-platform.c   | 237 +++---
 drivers/platform/x86/mlxcpld-hotplug.c| 515 -
 include/linux/platform_data/mlxcpld-hotplug.h |  99 
 include/linux/platform_data/mlxreg.h  | 144 ++
 12 files changed, 1001 insertions(+), 679 deletions(-)
 create mode 100644 drivers/platform/mellanox/Kconfig
 create mode 100644 drivers/platform/mellanox/Makefile
 create mode 100644 drivers/platform/mellanox/mlxreg-hotplug.c
 delete mode 100644 drivers/platform/x86/mlxcpld-hotplug.c
 delete mode 100644 include/linux/platform_data/mlxcpld-hotplug.h
 create mode 100644 include/linux/platform_data/mlxreg.h

-- 
2.1.4



Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Gang He



>>> 
> On 2018/1/11 12:31, Gang He wrote:
>> Hi Changwei,
>> 
>> 
>
>>> On 2018/1/11 11:33, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/11 10:07, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> On 2018/1/10 18:14, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/10 17:05, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> Hi Gang,
>>>
>>> On 2017/12/14 13:16, Gang He wrote:
 As you know, ocfs2 has support trim the underlying disk via
 fstrim command. But there is a problem, ocfs2 is a shared disk
 cluster file system, if the user configures a scheduled fstrim
 job on each file system node, this will trigger multiple nodes
 trim a shared disk simultaneously, it is very wasteful for CPU
 and IO consumption, also might negatively affect the lifetime
 of poor-quality SSD devices.
 Then, we introduce a trimfs dlm lock to communicate with each
 other in this case, which will make only one fstrim command to
 do the trimming on a shared disk among the cluster, the fstrim
 commands from the other nodes should wait for the first fstrim
 to finish and returned success directly, to avoid running a the
 same trim on the shared disk again.

 Compare with first version, I change the fstrim commands' returned
 value and behavior in case which meets a fstrim command is running
 on a shared disk.

 Signed-off-by: Gang He 
 ---
fs/ocfs2/alloc.c | 44 
 
1 file changed, 44 insertions(+)

 diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
 index ab5105f..5c9c3e2 100644
 --- a/fs/ocfs2/alloc.c
 +++ b/fs/ocfs2/alloc.c
 @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
 struct
>>> fstrim_range *range)
struct buffer_head *gd_bh = NULL;
struct ocfs2_dinode *main_bm;
struct ocfs2_group_desc *gd = NULL;
 +  struct ocfs2_trim_fs_info info, *pinfo = NULL;
>>>
>>> I think *pinfo* is not necessary.
>> This pointer is necessary, since it can be NULL or non-NULL depend 
>> on the
> code logic.
>
> This point is OK for me.
>
>>

start = range->start >> osb->s_clustersize_bits;
len = range->len >> osb->s_clustersize_bits;
 @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
 struct
>>> fstrim_range *range)

trace_ocfs2_trim_fs(start, len, minlen);

 +  ocfs2_trim_fs_lock_res_init(osb);
 +  ret = ocfs2_trim_fs_lock(osb, NULL, 1);
>>>
>>> I don't get why try to lock here and if fails, acquire the same 
>>> lock again
>>> later but wait until granted.
>> Please think about the user case, the patch is only used to handle 
>> this
> case.
>> When the administer configures a fstrim schedule task on each node, 
>> then
> each node will trigger a fstrim on shared disks concurrently.
>> In this case, we should avoid duplicated fstrim on a shared disk 
>> since this
> will waste CPU/IO resources and affect SSD lifetime sometimes.
>
> I'm not worrying about that trimfs will affect SSD's lifetime quite a 
> lot,
> since physical-logical address converting table resides in RAM while 
> SSD is
> working.
> And that table won't be at a big scale. My point here is not 
> affecting this
> patch. Just a tip here.
 This depend on SSD firmware implementation, but for secure-trim, it 
 really
>>> possibly affect SSD lifetime.

>> Firstly, we use try_lock to get fstrim dlm lock to identify if there 
>> is any
> other node which is doing fstrim on the disk.
>> If not, this node is the first one, this node should do fstrim 
>> operation on
> the disk.
>> If yes, this node is not the first one, this node should wait until 
>> the
> first node is done for fstrim operation, then return the result from 
> DLM
> lock's value.
>>
>>> Can it just acquire the _trimfs_ lock as a blocking one directly 
>>> here?
>> We can not do a blocking lock directly, since we need to identify if 
>> there
> is any 

Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Gang He



>>> 
> On 2018/1/11 12:31, Gang He wrote:
>> Hi Changwei,
>> 
>> 
>
>>> On 2018/1/11 11:33, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/11 10:07, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> On 2018/1/10 18:14, Gang He wrote:
 Hi Changwei,


>>>
> On 2018/1/10 17:05, Gang He wrote:
>> Hi Changwei,
>>
>>
>
>>> Hi Gang,
>>>
>>> On 2017/12/14 13:16, Gang He wrote:
 As you know, ocfs2 has support trim the underlying disk via
 fstrim command. But there is a problem, ocfs2 is a shared disk
 cluster file system, if the user configures a scheduled fstrim
 job on each file system node, this will trigger multiple nodes
 trim a shared disk simultaneously, it is very wasteful for CPU
 and IO consumption, also might negatively affect the lifetime
 of poor-quality SSD devices.
 Then, we introduce a trimfs dlm lock to communicate with each
 other in this case, which will make only one fstrim command to
 do the trimming on a shared disk among the cluster, the fstrim
 commands from the other nodes should wait for the first fstrim
 to finish and returned success directly, to avoid running a the
 same trim on the shared disk again.

 Compare with first version, I change the fstrim commands' returned
 value and behavior in case which meets a fstrim command is running
 on a shared disk.

 Signed-off-by: Gang He 
 ---
fs/ocfs2/alloc.c | 44 
 
1 file changed, 44 insertions(+)

 diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
 index ab5105f..5c9c3e2 100644
 --- a/fs/ocfs2/alloc.c
 +++ b/fs/ocfs2/alloc.c
 @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
 struct
>>> fstrim_range *range)
struct buffer_head *gd_bh = NULL;
struct ocfs2_dinode *main_bm;
struct ocfs2_group_desc *gd = NULL;
 +  struct ocfs2_trim_fs_info info, *pinfo = NULL;
>>>
>>> I think *pinfo* is not necessary.
>> This pointer is necessary, since it can be NULL or non-NULL depend 
>> on the
> code logic.
>
> This point is OK for me.
>
>>

start = range->start >> osb->s_clustersize_bits;
len = range->len >> osb->s_clustersize_bits;
 @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
 struct
>>> fstrim_range *range)

trace_ocfs2_trim_fs(start, len, minlen);

 +  ocfs2_trim_fs_lock_res_init(osb);
 +  ret = ocfs2_trim_fs_lock(osb, NULL, 1);
>>>
>>> I don't get why try to lock here and if fails, acquire the same 
>>> lock again
>>> later but wait until granted.
>> Please think about the user case, the patch is only used to handle 
>> this
> case.
>> When the administer configures a fstrim schedule task on each node, 
>> then
> each node will trigger a fstrim on shared disks concurrently.
>> In this case, we should avoid duplicated fstrim on a shared disk 
>> since this
> will waste CPU/IO resources and affect SSD lifetime sometimes.
>
> I'm not worrying about that trimfs will affect SSD's lifetime quite a 
> lot,
> since physical-logical address converting table resides in RAM while 
> SSD is
> working.
> And that table won't be at a big scale. My point here is not 
> affecting this
> patch. Just a tip here.
 This depend on SSD firmware implementation, but for secure-trim, it 
 really
>>> possibly affect SSD lifetime.

>> Firstly, we use try_lock to get fstrim dlm lock to identify if there 
>> is any
> other node which is doing fstrim on the disk.
>> If not, this node is the first one, this node should do fstrim 
>> operation on
> the disk.
>> If yes, this node is not the first one, this node should wait until 
>> the
> first node is done for fstrim operation, then return the result from 
> DLM
> lock's value.
>>
>>> Can it just acquire the _trimfs_ lock as a blocking one directly 
>>> here?
>> We can not do a blocking lock directly, since we need to identify if 
>> there
> is any other node has 

Re: [PATCH v2] zsmalloc: use U suffix for negative literals being shifted

2018-01-10 Thread Sergey Senozhatsky
On (01/10/18 19:41), Nick Desaulniers wrote:
> Fixes warnings about shifting unsigned literals being undefined
> behavior.
> 
> Suggested-by: Minchan Kim 
> Signed-off-by: Nick Desaulniers 

looks good to me.

Reviewed-by: Sergey Senozhatsky 

-ss


Re: [PATCH v2] zsmalloc: use U suffix for negative literals being shifted

2018-01-10 Thread Sergey Senozhatsky
On (01/10/18 19:41), Nick Desaulniers wrote:
> Fixes warnings about shifting unsigned literals being undefined
> behavior.
> 
> Suggested-by: Minchan Kim 
> Signed-off-by: Nick Desaulniers 

looks good to me.

Reviewed-by: Sergey Senozhatsky 

-ss


Re: [PATCH v3] zswap: only save zswap header when necessary

2018-01-10 Thread Sergey Senozhatsky
On (01/10/18 14:56), Yu Zhao wrote:
[..]
> We waste sizeof(swp_entry_t) for zswap header when using zsmalloc
> as zpool driver because zsmalloc doesn't support eviction.
>
> Add zpool_evictable() to detect if zpool is potentially evictable,
> and use it in zswap to avoid waste memory for zswap header.
>
> Signed-off-by: Yu Zhao 

looks good to me.

FWIW,
Reviewed-by: Sergey Senozhatsky 

-ss


Re: [PATCH v3] zswap: only save zswap header when necessary

2018-01-10 Thread Sergey Senozhatsky
On (01/10/18 14:56), Yu Zhao wrote:
[..]
> We waste sizeof(swp_entry_t) for zswap header when using zsmalloc
> as zpool driver because zsmalloc doesn't support eviction.
>
> Add zpool_evictable() to detect if zpool is potentially evictable,
> and use it in zswap to avoid waste memory for zswap header.
>
> Signed-off-by: Yu Zhao 

looks good to me.

FWIW,
Reviewed-by: Sergey Senozhatsky 

-ss


Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Changwei Ge
On 2018/1/11 12:31, Gang He wrote:
> Hi Changwei,
> 
> 

>> On 2018/1/11 11:33, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/11 10:07, Gang He wrote:
> Hi Changwei,
>
>

>> On 2018/1/10 18:14, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/10 17:05, Gang He wrote:
> Hi Changwei,
>
>

>> Hi Gang,
>>
>> On 2017/12/14 13:16, Gang He wrote:
>>> As you know, ocfs2 has support trim the underlying disk via
>>> fstrim command. But there is a problem, ocfs2 is a shared disk
>>> cluster file system, if the user configures a scheduled fstrim
>>> job on each file system node, this will trigger multiple nodes
>>> trim a shared disk simultaneously, it is very wasteful for CPU
>>> and IO consumption, also might negatively affect the lifetime
>>> of poor-quality SSD devices.
>>> Then, we introduce a trimfs dlm lock to communicate with each
>>> other in this case, which will make only one fstrim command to
>>> do the trimming on a shared disk among the cluster, the fstrim
>>> commands from the other nodes should wait for the first fstrim
>>> to finish and returned success directly, to avoid running a the
>>> same trim on the shared disk again.
>>>
>>> Compare with first version, I change the fstrim commands' returned
>>> value and behavior in case which meets a fstrim command is running
>>> on a shared disk.
>>>
>>> Signed-off-by: Gang He 
>>> ---
>>>fs/ocfs2/alloc.c | 44 
>>> 
>>>1 file changed, 44 insertions(+)
>>>
>>> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
>>> index ab5105f..5c9c3e2 100644
>>> --- a/fs/ocfs2/alloc.c
>>> +++ b/fs/ocfs2/alloc.c
>>> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
>>> struct
>> fstrim_range *range)
>>> struct buffer_head *gd_bh = NULL;
>>> struct ocfs2_dinode *main_bm;
>>> struct ocfs2_group_desc *gd = NULL;
>>> +   struct ocfs2_trim_fs_info info, *pinfo = NULL;
>>
>> I think *pinfo* is not necessary.
> This pointer is necessary, since it can be NULL or non-NULL depend on 
> the
 code logic.

 This point is OK for me.

>
>>>
>>> start = range->start >> osb->s_clustersize_bits;
>>> len = range->len >> osb->s_clustersize_bits;
>>> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
>>> struct
>> fstrim_range *range)
>>>
>>> trace_ocfs2_trim_fs(start, len, minlen);
>>>
>>> +   ocfs2_trim_fs_lock_res_init(osb);
>>> +   ret = ocfs2_trim_fs_lock(osb, NULL, 1);
>>
>> I don't get why try to lock here and if fails, acquire the same lock 
>> again
>> later but wait until granted.
> Please think about the user case, the patch is only used to handle 
> this
 case.
> When the administer configures a fstrim schedule task on each node, 
> then
 each node will trigger a fstrim on shared disks concurrently.
> In this case, we should avoid duplicated fstrim on a shared disk 
> since this
 will waste CPU/IO resources and affect SSD lifetime sometimes.

 I'm not worrying about that trimfs will affect SSD's lifetime quite a 
 lot,
 since physical-logical address converting table resides in RAM while 
 SSD is
 working.
 And that table won't be at a big scale. My point here is not affecting 
 this
 patch. Just a tip here.
>>> This depend on SSD firmware implementation, but for secure-trim, it 
>>> really
>> possibly affect SSD lifetime.
>>>
> Firstly, we use try_lock to get fstrim dlm lock to identify if there 
> is any
 other node which is doing fstrim on the disk.
> If not, this node is the first one, this node should do fstrim 
> operation on
 the disk.
> If yes, this node is not the first one, this node should wait until 
> the
 first node is done for fstrim operation, then return the result from 
 DLM
 lock's value.
>
>> Can it just acquire the _trimfs_ lock as a blocking one directly 
>> here?
> We can not do a blocking lock directly, since we need to identify if 
> there
 is any other node has being do fstrim operation when this node start 
 to do
 fstrim.

 Thanks for your 

Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-10 Thread Changwei Ge
On 2018/1/11 12:31, Gang He wrote:
> Hi Changwei,
> 
> 

>> On 2018/1/11 11:33, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/11 10:07, Gang He wrote:
> Hi Changwei,
>
>

>> On 2018/1/10 18:14, Gang He wrote:
>>> Hi Changwei,
>>>
>>>
>>
 On 2018/1/10 17:05, Gang He wrote:
> Hi Changwei,
>
>

>> Hi Gang,
>>
>> On 2017/12/14 13:16, Gang He wrote:
>>> As you know, ocfs2 has support trim the underlying disk via
>>> fstrim command. But there is a problem, ocfs2 is a shared disk
>>> cluster file system, if the user configures a scheduled fstrim
>>> job on each file system node, this will trigger multiple nodes
>>> trim a shared disk simultaneously, it is very wasteful for CPU
>>> and IO consumption, also might negatively affect the lifetime
>>> of poor-quality SSD devices.
>>> Then, we introduce a trimfs dlm lock to communicate with each
>>> other in this case, which will make only one fstrim command to
>>> do the trimming on a shared disk among the cluster, the fstrim
>>> commands from the other nodes should wait for the first fstrim
>>> to finish and returned success directly, to avoid running a the
>>> same trim on the shared disk again.
>>>
>>> Compare with first version, I change the fstrim commands' returned
>>> value and behavior in case which meets a fstrim command is running
>>> on a shared disk.
>>>
>>> Signed-off-by: Gang He 
>>> ---
>>>fs/ocfs2/alloc.c | 44 
>>> 
>>>1 file changed, 44 insertions(+)
>>>
>>> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
>>> index ab5105f..5c9c3e2 100644
>>> --- a/fs/ocfs2/alloc.c
>>> +++ b/fs/ocfs2/alloc.c
>>> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, 
>>> struct
>> fstrim_range *range)
>>> struct buffer_head *gd_bh = NULL;
>>> struct ocfs2_dinode *main_bm;
>>> struct ocfs2_group_desc *gd = NULL;
>>> +   struct ocfs2_trim_fs_info info, *pinfo = NULL;
>>
>> I think *pinfo* is not necessary.
> This pointer is necessary, since it can be NULL or non-NULL depend on 
> the
 code logic.

 This point is OK for me.

>
>>>
>>> start = range->start >> osb->s_clustersize_bits;
>>> len = range->len >> osb->s_clustersize_bits;
>>> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, 
>>> struct
>> fstrim_range *range)
>>>
>>> trace_ocfs2_trim_fs(start, len, minlen);
>>>
>>> +   ocfs2_trim_fs_lock_res_init(osb);
>>> +   ret = ocfs2_trim_fs_lock(osb, NULL, 1);
>>
>> I don't get why try to lock here and if fails, acquire the same lock 
>> again
>> later but wait until granted.
> Please think about the user case, the patch is only used to handle 
> this
 case.
> When the administer configures a fstrim schedule task on each node, 
> then
 each node will trigger a fstrim on shared disks concurrently.
> In this case, we should avoid duplicated fstrim on a shared disk 
> since this
 will waste CPU/IO resources and affect SSD lifetime sometimes.

 I'm not worrying about that trimfs will affect SSD's lifetime quite a 
 lot,
 since physical-logical address converting table resides in RAM while 
 SSD is
 working.
 And that table won't be at a big scale. My point here is not affecting 
 this
 patch. Just a tip here.
>>> This depend on SSD firmware implementation, but for secure-trim, it 
>>> really
>> possibly affect SSD lifetime.
>>>
> Firstly, we use try_lock to get fstrim dlm lock to identify if there 
> is any
 other node which is doing fstrim on the disk.
> If not, this node is the first one, this node should do fstrim 
> operation on
 the disk.
> If yes, this node is not the first one, this node should wait until 
> the
 first node is done for fstrim operation, then return the result from 
 DLM
 lock's value.
>
>> Can it just acquire the _trimfs_ lock as a blocking one directly 
>> here?
> We can not do a blocking lock directly, since we need to identify if 
> there
 is any other node has being do fstrim operation when this node start 
 to do
 fstrim.

 Thanks for your elaboration.

Re: [PATCH] zswap: only save zswap header if zpool is shrinkable

2018-01-10 Thread Sergey Senozhatsky
Hello,

Yu Zhao, Dan, sorry for the delay


On (01/10/18 15:06), Dan Streetman wrote:
[..]
> Well, I think shrink vs evict an implementation detail, isn't it?
> That is, from zswap's perspective, there should be:
> 
> zpool_evictable()
> if true, zswap needs to include the header on each compressed page,
> because the zpool may callback zpool->ops->evict() which calls
> zswap_writeback_entry() which expects the entry to start with a zswap
> header.
> if false, zswap doesn't need to include the header, because the zpool
> will never, ever call zpool->ops->evict
> 
> zpool_shrink()
> this will try to shrink the zpool, using whatever
> zpool-implementation-specific shrinking method.  If zpool_evictable()
> is true for this zpool, then zpool_shrink() *might* callback to
> zpool->ops->evict(), although it doesn't have to if it can shrink
> without evictions.  If zpool_evictable() is false, then zpool_shrink()
> will never callback to zpool->ops->evict().

ACK on this!

-ss


Re: [PATCH] zswap: only save zswap header if zpool is shrinkable

2018-01-10 Thread Sergey Senozhatsky
Hello,

Yu Zhao, Dan, sorry for the delay


On (01/10/18 15:06), Dan Streetman wrote:
[..]
> Well, I think shrink vs evict an implementation detail, isn't it?
> That is, from zswap's perspective, there should be:
> 
> zpool_evictable()
> if true, zswap needs to include the header on each compressed page,
> because the zpool may callback zpool->ops->evict() which calls
> zswap_writeback_entry() which expects the entry to start with a zswap
> header.
> if false, zswap doesn't need to include the header, because the zpool
> will never, ever call zpool->ops->evict
> 
> zpool_shrink()
> this will try to shrink the zpool, using whatever
> zpool-implementation-specific shrinking method.  If zpool_evictable()
> is true for this zpool, then zpool_shrink() *might* callback to
> zpool->ops->evict(), although it doesn't have to if it can shrink
> without evictions.  If zpool_evictable() is false, then zpool_shrink()
> will never callback to zpool->ops->evict().

ACK on this!

-ss


Re: [PATCH v2] f2fs: handle newly created page when revoking inmem pages

2018-01-10 Thread Yunlong Song

Should it be "When committing inmem pages is not successful" ?

On 2018/1/11 8:17, Daeho Jeong wrote:

When committing inmem pages is successful, we revoke already committed
blocks in __revoke_inmem_pages() and finally replace the committed
ones with the old blocks using f2fs_replace_block(). However, if
the committed block was newly created one, the address of the old
block is NEW_ADDR and __f2fs_replace_block() cannot handle NEW_ADDR
as new_blkaddr properly and a kernel panic occurrs.

Signed-off-by: Daeho Jeong 
Tested-by: Shu Tan 
Reviewed-by: Chao Yu 
---
  fs/f2fs/segment.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c117e09..0673d08 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -248,7 +248,11 @@ static int __revoke_inmem_pages(struct inode *inode,
goto next;
}
get_node_info(sbi, dn.nid, );
-   f2fs_replace_block(sbi, , dn.data_blkaddr,
+   if (cur->old_addr == NEW_ADDR) {
+   invalidate_blocks(sbi, dn.data_blkaddr);
+   f2fs_update_data_blkaddr(, NEW_ADDR);
+   } else
+   f2fs_replace_block(sbi, , dn.data_blkaddr,
cur->old_addr, ni.version, true, true);
f2fs_put_dnode();
}



--
Thanks,
Yunlong Song



Re: [PATCH v2] f2fs: handle newly created page when revoking inmem pages

2018-01-10 Thread Yunlong Song

Should it be "When committing inmem pages is not successful" ?

On 2018/1/11 8:17, Daeho Jeong wrote:

When committing inmem pages is successful, we revoke already committed
blocks in __revoke_inmem_pages() and finally replace the committed
ones with the old blocks using f2fs_replace_block(). However, if
the committed block was newly created one, the address of the old
block is NEW_ADDR and __f2fs_replace_block() cannot handle NEW_ADDR
as new_blkaddr properly and a kernel panic occurrs.

Signed-off-by: Daeho Jeong 
Tested-by: Shu Tan 
Reviewed-by: Chao Yu 
---
  fs/f2fs/segment.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c117e09..0673d08 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -248,7 +248,11 @@ static int __revoke_inmem_pages(struct inode *inode,
goto next;
}
get_node_info(sbi, dn.nid, );
-   f2fs_replace_block(sbi, , dn.data_blkaddr,
+   if (cur->old_addr == NEW_ADDR) {
+   invalidate_blocks(sbi, dn.data_blkaddr);
+   f2fs_update_data_blkaddr(, NEW_ADDR);
+   } else
+   f2fs_replace_block(sbi, , dn.data_blkaddr,
cur->old_addr, ni.version, true, true);
f2fs_put_dnode();
}



--
Thanks,
Yunlong Song



[PATCH v2 00/16] ASoC: fsl_ssi: Clean up - program flow level

2018-01-10 Thread Nicolin Chen
==Change log==
v2
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to keep all ssi->i2s_net updated
  + Replaced bool tx with bool dir in PATCH-03 and PATCH-06
  + Moved all initial register configurations from dai probe() to
platform probe() so as to let AC97 CODEC successfully probe.
 * Added Tested-by from Caleb for TDM test cases.

==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 second set to clean up fsl_ssi driver
in the program flow level. Any patch here may impact a fundamental
test case like playback or record.

==Verification==
This series of patches require fully tested. I have done such tests
on i.MX6SoloX with WM8962 using imx_v6_v7_defconfig as:
 - Playback via I2S Master and Slave mode
 - Record via I2S Master and Slave mode
 - Simultaneous playback and record via I2S Master and Slave mode
 - Background playback with foreground record (starting at different
   time) via I2S Master and Slave mode
 - Background record with foreground playback (starting at different
   time) via I2S Master and Slave mode
 * All tests above by hacking offline_config to true in imx51.

Caleb has tested v1 with TDM lookback tests on i.MX6.

Example of uncovered tests: AC97, PowerPC and FIQ.

Nicolin Chen (16):
  ASoC: fsl_ssi: Keep ssi->i2s_net updated
  ASoC: fsl_ssi: Clean up set_dai_tdm_slot()
  ASoC: fsl_ssi: Maintain a mask of active streams
  ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro
  ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()
  ASoC: fsl_ssi: Clean up helper functions of trigger()
  ASoC: fsl_ssi: Add DAIFMT define for AC97
  ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()
  ASoC: fsl_ssi: Set xFEN0 and xFEN1 together
  ASoC: fsl_ssi: Use snd_soc_init_dma_data instead
  ASoC: fsl_ssi: Move one-time configurations to probe()
  ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()
  ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()
  ASoC: fsl_ssi: Remove cpu_dai_drv from fsl_ssi structure
  ASoC: fsl_ssi: Move DT related code to a separate probe()
  ASoC: fsl_ssi: Use ssi->streams instead of reading register

 sound/soc/fsl/fsl_ssi.c | 740 
 1 file changed, 369 insertions(+), 371 deletions(-)

-- 
2.7.4



[PATCH v2 00/16] ASoC: fsl_ssi: Clean up - program flow level

2018-01-10 Thread Nicolin Chen
==Change log==
v2
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to keep all ssi->i2s_net updated
  + Replaced bool tx with bool dir in PATCH-03 and PATCH-06
  + Moved all initial register configurations from dai probe() to
platform probe() so as to let AC97 CODEC successfully probe.
 * Added Tested-by from Caleb for TDM test cases.

==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 second set to clean up fsl_ssi driver
in the program flow level. Any patch here may impact a fundamental
test case like playback or record.

==Verification==
This series of patches require fully tested. I have done such tests
on i.MX6SoloX with WM8962 using imx_v6_v7_defconfig as:
 - Playback via I2S Master and Slave mode
 - Record via I2S Master and Slave mode
 - Simultaneous playback and record via I2S Master and Slave mode
 - Background playback with foreground record (starting at different
   time) via I2S Master and Slave mode
 - Background record with foreground playback (starting at different
   time) via I2S Master and Slave mode
 * All tests above by hacking offline_config to true in imx51.

Caleb has tested v1 with TDM lookback tests on i.MX6.

Example of uncovered tests: AC97, PowerPC and FIQ.

Nicolin Chen (16):
  ASoC: fsl_ssi: Keep ssi->i2s_net updated
  ASoC: fsl_ssi: Clean up set_dai_tdm_slot()
  ASoC: fsl_ssi: Maintain a mask of active streams
  ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro
  ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()
  ASoC: fsl_ssi: Clean up helper functions of trigger()
  ASoC: fsl_ssi: Add DAIFMT define for AC97
  ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()
  ASoC: fsl_ssi: Set xFEN0 and xFEN1 together
  ASoC: fsl_ssi: Use snd_soc_init_dma_data instead
  ASoC: fsl_ssi: Move one-time configurations to probe()
  ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()
  ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()
  ASoC: fsl_ssi: Remove cpu_dai_drv from fsl_ssi structure
  ASoC: fsl_ssi: Move DT related code to a separate probe()
  ASoC: fsl_ssi: Use ssi->streams instead of reading register

 sound/soc/fsl/fsl_ssi.c | 740 
 1 file changed, 369 insertions(+), 371 deletions(-)

-- 
2.7.4



[PATCH v2 05/16] ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()

2018-01-10 Thread Nicolin Chen
The FIFO clear helper function is just one line of code now.
So it could be cleaned up by removing it and calling regmap
directly.

Meanwhile, FIFO clear could be applied to all use cases, not
confined to AC97. So this patch also moves FIFO clear in the
trigger() to fsl_ssi_config() and removes the AC97 check.

Note that SOR register is safe from offline_config HW limit.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 31 +--
 1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index f026386..263c067 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -406,17 +406,6 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 }
 
 /**
- * Clear remaining data in the FIFO to avoid dirty data or channel slipping
- */
-static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
-{
-   bool tx = !is_rx;
-
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
-}
-
-/**
  * Exclude bits that are used by the opposite stream
  *
  * When both streams are active, disabling some bits for the current stream
@@ -442,7 +431,8 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
-   bool dir = (>regvals[TX] == vals) ? TX : RX;
+   bool tx = >regvals[TX] == vals;
+   bool dir = tx ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
bool aactive;
@@ -484,7 +474,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
/* Online configure single direction while SSI is running */
if (enable) {
-   fsl_ssi_fifo_clear(ssi, vals->scr & SSI_SCR_RE);
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 
regmap_update_bits(regs, REG_SSI_SRCR, vals->srcr, vals->srcr);
regmap_update_bits(regs, REG_SSI_STCR, vals->stcr, vals->stcr);
@@ -506,6 +498,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
regmap_update_bits(regs, REG_SSI_SRCR, srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR, stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER, sier, 0);
+
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
}
 
 config_done:
@@ -1086,7 +1082,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-   struct regmap *regs = ssi->regs;
 
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -,14 +1106,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
return -EINVAL;
}
 
-   /* Clear corresponding FIFO */
-   if (fsl_ssi_is_ac97(ssi)) {
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_TX_CLR);
-   else
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_RX_CLR);
-   }
-
return 0;
 }
 
-- 
2.7.4



[PATCH v2 05/16] ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()

2018-01-10 Thread Nicolin Chen
The FIFO clear helper function is just one line of code now.
So it could be cleaned up by removing it and calling regmap
directly.

Meanwhile, FIFO clear could be applied to all use cases, not
confined to AC97. So this patch also moves FIFO clear in the
trigger() to fsl_ssi_config() and removes the AC97 check.

Note that SOR register is safe from offline_config HW limit.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 31 +--
 1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index f026386..263c067 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -406,17 +406,6 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 }
 
 /**
- * Clear remaining data in the FIFO to avoid dirty data or channel slipping
- */
-static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
-{
-   bool tx = !is_rx;
-
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
-}
-
-/**
  * Exclude bits that are used by the opposite stream
  *
  * When both streams are active, disabling some bits for the current stream
@@ -442,7 +431,8 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
-   bool dir = (>regvals[TX] == vals) ? TX : RX;
+   bool tx = >regvals[TX] == vals;
+   bool dir = tx ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
bool aactive;
@@ -484,7 +474,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
/* Online configure single direction while SSI is running */
if (enable) {
-   fsl_ssi_fifo_clear(ssi, vals->scr & SSI_SCR_RE);
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 
regmap_update_bits(regs, REG_SSI_SRCR, vals->srcr, vals->srcr);
regmap_update_bits(regs, REG_SSI_STCR, vals->stcr, vals->stcr);
@@ -506,6 +498,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
regmap_update_bits(regs, REG_SSI_SRCR, srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR, stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER, sier, 0);
+
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
}
 
 config_done:
@@ -1086,7 +1082,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-   struct regmap *regs = ssi->regs;
 
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -,14 +1106,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
return -EINVAL;
}
 
-   /* Clear corresponding FIFO */
-   if (fsl_ssi_is_ac97(ssi)) {
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_TX_CLR);
-   else
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_RX_CLR);
-   }
-
return 0;
 }
 
-- 
2.7.4



[PATCH V3 3/6] usb: serial: f81534: add output pin control

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had 3 output pin (M0/SD, M1, M2) with open-drain mode to
control transceiver. We'll read it from internal Flash with address
0x2f05~0x2f08 for 4 ports. The value is range from 0 to 7. The M0/SD is
MSB of this value. For a examples, If read value is 6, we'll write M0/SD,
M1, M2 as 1, 1, 0.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: change reg_mask type from u16 to u8.
2: change space around "{" & "}".

V2:
1: Fix for space between brace.
2: Remain the old pin control method.

 drivers/usb/serial/f81534.c | 67 -
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 2201be577dd3..e7dd01310f20 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -52,6 +52,7 @@
 #define F81534_CUSTOM_NO_CUSTOM_DATA   0xff
 #define F81534_CUSTOM_VALID_TOKEN  0xf0
 #define F81534_CONF_OFFSET 1
+#define F81534_CONF_GPIO_OFFSET4
 
 #define F81534_MAX_DATA_BLOCK  64
 #define F81534_MAX_BUS_RETRY   20
@@ -164,6 +165,23 @@ struct f81534_port_private {
u8 phy_num;
 };
 
+struct f81534_pin_data {
+   const u16 reg_addr;
+   const u8 reg_mask;
+};
+
+struct f81534_port_out_pin {
+   struct f81534_pin_data pin[3];
+};
+
+/* Pin output value for M2/M1/M0(SD) */
+static const struct f81534_port_out_pin f81534_port_out_pins[] = {
+{ { { 0x2ae8, BIT(7) }, { 0x2a90, BIT(5) }, { 0x2a90, BIT(4) } } },
+{ { { 0x2ae8, BIT(6) }, { 0x2ae8, BIT(0) }, { 0x2ae8, BIT(3) } } },
+{ { { 0x2a90, BIT(0) }, { 0x2ae8, BIT(2) }, { 0x2a80, BIT(6) } } },
+{ { { 0x2a90, BIT(3) }, { 0x2a90, BIT(2) }, { 0x2a90, BIT(1) } } },
+};
+
 static u32 const baudrate_table[] = { 115200, 921600, 1152000, 150 };
 static u8 const clock_table[] = { F81534_CLK_1_846_MHZ, F81534_CLK_14_77_MHZ,
F81534_CLK_18_46_MHZ, F81534_CLK_24_MHZ };
@@ -273,6 +291,22 @@ static int f81534_get_register(struct usb_serial *serial, 
u16 reg, u8 *data)
return status;
 }
 
+static int f81534_set_mask_register(struct usb_serial *serial, u16 reg,
+   u8 mask, u8 data)
+{
+   int status;
+   u8 tmp;
+
+   status = f81534_get_register(serial, reg, );
+   if (status)
+   return status;
+
+   tmp &= ~mask;
+   tmp |= (mask & data);
+
+   return f81534_set_register(serial, reg, tmp);
+}
+
 static int f81534_set_port_register(struct usb_serial_port *port, u16 reg,
u8 data)
 {
@@ -1281,6 +1315,37 @@ static void f81534_lsr_worker(struct work_struct *work)
dev_warn(>dev, "read LSR failed: %d\n", status);
 }
 
+static int f81534_set_port_output_pin(struct usb_serial_port *port)
+{
+   struct f81534_serial_private *serial_priv;
+   struct f81534_port_private *port_priv;
+   struct usb_serial *serial;
+   const struct f81534_port_out_pin *pins;
+   int status;
+   int i;
+   u8 value;
+   u8 idx;
+
+   serial = port->serial;
+   serial_priv = usb_get_serial_data(serial);
+   port_priv = usb_get_serial_port_data(port);
+
+   idx = F81534_CONF_GPIO_OFFSET + port_priv->phy_num;
+   value = serial_priv->conf_data[idx];
+   pins = _port_out_pins[port_priv->phy_num];
+
+   for (i = 0; i < ARRAY_SIZE(pins->pin); ++i) {
+   status = f81534_set_mask_register(serial,
+   pins->pin[i].reg_addr, pins->pin[i].reg_mask,
+   value & BIT(i) ? pins->pin[i].reg_mask : 0);
+   if (status)
+   return status;
+   }
+
+   dev_dbg(>dev, "Output pin (M0/M1/M2): %d\n", value);
+   return 0;
+}
+
 static int f81534_port_probe(struct usb_serial_port *port)
 {
struct f81534_serial_private *serial_priv;
@@ -1339,7 +1404,7 @@ static int f81534_port_probe(struct usb_serial_port *port)
break;
}
 
-   return 0;
+   return f81534_set_port_output_pin(port);
 }
 
 static int f81534_port_remove(struct usb_serial_port *port)
-- 
2.7.4



[PATCH v2 01/16] ASoC: fsl_ssi: Keep ssi->i2s_net updated

2018-01-10 Thread Nicolin Chen
The hw_params() overwrites i2s_net settings for special cases like
mono-channel support, however, it doesn't update ssi->i2s_net as
set_dai_fmt() does.

This patch removes the local i2s_net variable and directly updates
ssi->i2s_net in the hw_params() so that the driver can simply look
up the ssi->i2s_net instead of reading the register.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 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 aecd00f..c8bd353 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -834,16 +834,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   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)
-   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
-   else
-   i2s_net = ssi->i2s_net;
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+
+   /* Use Normal mode to send mono data at 1st slot of 2 slots */
+   if (channels == 1)
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_I2S_NET_MASK,
-  channels == 1 ? 0 : i2s_net);
+  SSI_SCR_I2S_NET_MASK, ssi->i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-- 
2.7.4



[PATCH v2 03/16] ASoC: fsl_ssi: Maintain a mask of active streams

2018-01-10 Thread Nicolin Chen
Checking TE and RE bits in SCR register doesn't work for AC97 mode
which enables SSIEN, TE and RE in the fsl_ssi_setup_ac97() that's
called during probe().

So when running into the trigger(), it will always get the result
of both TE and RE being enabled already, even if actually there is
no active stream.

This patch fixes this issue by adding a variable to log the active
streams manually.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 491b660..aa14a5d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -201,6 +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
+ * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @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
@@ -245,6 +246,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
+   u8 streams;
u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
@@ -440,15 +442,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   bool dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
int nr_active_streams;
-   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, );
-
-   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
+   nr_active_streams = !!(ssi->streams & BIT(TX)) +
+   !!(ssi->streams & BIT(RX));
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -470,6 +471,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
  keep_active);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
+
+   /* Log the disabled stream to the mask */
+   ssi->streams &= ~BIT(dir);
}
 
/*
@@ -545,6 +549,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
}
/* Enable all remaining bits */
regmap_update_bits(regs, REG_SSI_SCR, vals->scr, vals->scr);
+
+   /* Log the enabled stream to the mask */
+   ssi->streams |= BIT(dir);
}
 }
 
-- 
2.7.4



[PATCH V3 3/6] usb: serial: f81534: add output pin control

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had 3 output pin (M0/SD, M1, M2) with open-drain mode to
control transceiver. We'll read it from internal Flash with address
0x2f05~0x2f08 for 4 ports. The value is range from 0 to 7. The M0/SD is
MSB of this value. For a examples, If read value is 6, we'll write M0/SD,
M1, M2 as 1, 1, 0.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: change reg_mask type from u16 to u8.
2: change space around "{" & "}".

V2:
1: Fix for space between brace.
2: Remain the old pin control method.

 drivers/usb/serial/f81534.c | 67 -
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 2201be577dd3..e7dd01310f20 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -52,6 +52,7 @@
 #define F81534_CUSTOM_NO_CUSTOM_DATA   0xff
 #define F81534_CUSTOM_VALID_TOKEN  0xf0
 #define F81534_CONF_OFFSET 1
+#define F81534_CONF_GPIO_OFFSET4
 
 #define F81534_MAX_DATA_BLOCK  64
 #define F81534_MAX_BUS_RETRY   20
@@ -164,6 +165,23 @@ struct f81534_port_private {
u8 phy_num;
 };
 
+struct f81534_pin_data {
+   const u16 reg_addr;
+   const u8 reg_mask;
+};
+
+struct f81534_port_out_pin {
+   struct f81534_pin_data pin[3];
+};
+
+/* Pin output value for M2/M1/M0(SD) */
+static const struct f81534_port_out_pin f81534_port_out_pins[] = {
+{ { { 0x2ae8, BIT(7) }, { 0x2a90, BIT(5) }, { 0x2a90, BIT(4) } } },
+{ { { 0x2ae8, BIT(6) }, { 0x2ae8, BIT(0) }, { 0x2ae8, BIT(3) } } },
+{ { { 0x2a90, BIT(0) }, { 0x2ae8, BIT(2) }, { 0x2a80, BIT(6) } } },
+{ { { 0x2a90, BIT(3) }, { 0x2a90, BIT(2) }, { 0x2a90, BIT(1) } } },
+};
+
 static u32 const baudrate_table[] = { 115200, 921600, 1152000, 150 };
 static u8 const clock_table[] = { F81534_CLK_1_846_MHZ, F81534_CLK_14_77_MHZ,
F81534_CLK_18_46_MHZ, F81534_CLK_24_MHZ };
@@ -273,6 +291,22 @@ static int f81534_get_register(struct usb_serial *serial, 
u16 reg, u8 *data)
return status;
 }
 
+static int f81534_set_mask_register(struct usb_serial *serial, u16 reg,
+   u8 mask, u8 data)
+{
+   int status;
+   u8 tmp;
+
+   status = f81534_get_register(serial, reg, );
+   if (status)
+   return status;
+
+   tmp &= ~mask;
+   tmp |= (mask & data);
+
+   return f81534_set_register(serial, reg, tmp);
+}
+
 static int f81534_set_port_register(struct usb_serial_port *port, u16 reg,
u8 data)
 {
@@ -1281,6 +1315,37 @@ static void f81534_lsr_worker(struct work_struct *work)
dev_warn(>dev, "read LSR failed: %d\n", status);
 }
 
+static int f81534_set_port_output_pin(struct usb_serial_port *port)
+{
+   struct f81534_serial_private *serial_priv;
+   struct f81534_port_private *port_priv;
+   struct usb_serial *serial;
+   const struct f81534_port_out_pin *pins;
+   int status;
+   int i;
+   u8 value;
+   u8 idx;
+
+   serial = port->serial;
+   serial_priv = usb_get_serial_data(serial);
+   port_priv = usb_get_serial_port_data(port);
+
+   idx = F81534_CONF_GPIO_OFFSET + port_priv->phy_num;
+   value = serial_priv->conf_data[idx];
+   pins = _port_out_pins[port_priv->phy_num];
+
+   for (i = 0; i < ARRAY_SIZE(pins->pin); ++i) {
+   status = f81534_set_mask_register(serial,
+   pins->pin[i].reg_addr, pins->pin[i].reg_mask,
+   value & BIT(i) ? pins->pin[i].reg_mask : 0);
+   if (status)
+   return status;
+   }
+
+   dev_dbg(>dev, "Output pin (M0/M1/M2): %d\n", value);
+   return 0;
+}
+
 static int f81534_port_probe(struct usb_serial_port *port)
 {
struct f81534_serial_private *serial_priv;
@@ -1339,7 +1404,7 @@ static int f81534_port_probe(struct usb_serial_port *port)
break;
}
 
-   return 0;
+   return f81534_set_port_output_pin(port);
 }
 
 static int f81534_port_remove(struct usb_serial_port *port)
-- 
2.7.4



[PATCH v2 01/16] ASoC: fsl_ssi: Keep ssi->i2s_net updated

2018-01-10 Thread Nicolin Chen
The hw_params() overwrites i2s_net settings for special cases like
mono-channel support, however, it doesn't update ssi->i2s_net as
set_dai_fmt() does.

This patch removes the local i2s_net variable and directly updates
ssi->i2s_net in the hw_params() so that the driver can simply look
up the ssi->i2s_net instead of reading the register.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 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 aecd00f..c8bd353 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -834,16 +834,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   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)
-   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
-   else
-   i2s_net = ssi->i2s_net;
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+
+   /* Use Normal mode to send mono data at 1st slot of 2 slots */
+   if (channels == 1)
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_I2S_NET_MASK,
-  channels == 1 ? 0 : i2s_net);
+  SSI_SCR_I2S_NET_MASK, ssi->i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-- 
2.7.4



[PATCH v2 03/16] ASoC: fsl_ssi: Maintain a mask of active streams

2018-01-10 Thread Nicolin Chen
Checking TE and RE bits in SCR register doesn't work for AC97 mode
which enables SSIEN, TE and RE in the fsl_ssi_setup_ac97() that's
called during probe().

So when running into the trigger(), it will always get the result
of both TE and RE being enabled already, even if actually there is
no active stream.

This patch fixes this issue by adding a variable to log the active
streams manually.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 491b660..aa14a5d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -201,6 +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
+ * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @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
@@ -245,6 +246,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
+   u8 streams;
u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
@@ -440,15 +442,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   bool dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
int nr_active_streams;
-   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, );
-
-   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
+   nr_active_streams = !!(ssi->streams & BIT(TX)) +
+   !!(ssi->streams & BIT(RX));
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -470,6 +471,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
  keep_active);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
+
+   /* Log the disabled stream to the mask */
+   ssi->streams &= ~BIT(dir);
}
 
/*
@@ -545,6 +549,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
}
/* Enable all remaining bits */
regmap_update_bits(regs, REG_SSI_SCR, vals->scr, vals->scr);
+
+   /* Log the enabled stream to the mask */
+   ssi->streams |= BIT(dir);
}
 }
 
-- 
2.7.4



[PATCH V3 2/6] usb: serial: f81534: add auto RTS direction support

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had auto RTS direction support for RS485 mode.
We'll read it from internal Flash with address 0x2f01~0x2f04 for 4 ports.
There are 4 conditions below:
0: F81534_PORT_CONF_RS232.
1: F81534_PORT_CONF_RS485.
2: value error, default to F81534_PORT_CONF_RS232.
3: F81534_PORT_CONF_RS485_INVERT.

F81532/534 Clock register (offset +08h)

Bit0:   UART Enable (always on)
Bit2-1: Clock source selector
00: 1.846MHz.
01: 18.46MHz.
10: 24MHz.
11: 14.77MHz.
Bit4:   Auto direction(RTS) control (RTS pin Low when TX)
Bit5:   Invert direction(RTS) when Bit4 enabled (RTS pin high when TX)

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: change some BIT() operation to GENMASK().
2: change some dev_info() to dev_dbg().

V2:
1: Read the configure data from flash and save it to shadow clock
   register.

 drivers/usb/serial/f81534.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 1563d3f34381..2201be577dd3 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -98,11 +98,16 @@
 
 #define F81534_DEFAULT_BAUD_RATE   9600
 
+#define F81534_PORT_CONF_RS232 0
+#define F81534_PORT_CONF_RS485 BIT(0)
+#define F81534_PORT_CONF_RS485_INVERT  GENMASK(1, 0)
 #define F81534_PORT_CONF_DISABLE_PORT  BIT(3)
 #define F81534_PORT_CONF_NOT_EXIST_PORTBIT(7)
 #define F81534_PORT_UNAVAILABLE\
(F81534_PORT_CONF_DISABLE_PORT | F81534_PORT_CONF_NOT_EXIST_PORT)
 
+#define F81534_UART_MODE_MASK  GENMASK(1, 0)
+
 #define F81534_1X_RXTRIGGER0xc3
 #define F81534_8X_RXTRIGGER0xcf
 
@@ -115,6 +120,8 @@
  * 01: 18.46MHz.
  * 10: 24MHz.
  * 11: 14.77MHz.
+ * Bit4:   Auto direction(RTS) control (RTS pin Low when TX)
+ * Bit5:   Invert direction(RTS) when Bit4 enabled (RTS pin high when TX)
  */
 
 #define F81534_UART_EN BIT(0)
@@ -123,6 +130,8 @@
 #define F81534_CLK_24_MHZ  BIT(2)
 #define F81534_CLK_14_77_MHZ   GENMASK(2, 1)
 #define F81534_CLK_MASKGENMASK(2, 1)
+#define F81534_CLK_RS485_MODE  BIT(4)
+#define F81534_CLK_RS485_INVERTBIT(5)
 
 static const struct usb_device_id f81534_id_table[] = {
{ USB_DEVICE(FINTEK_VENDOR_ID_1, FINTEK_DEVICE_ID) },
@@ -1274,9 +1283,12 @@ static void f81534_lsr_worker(struct work_struct *work)
 
 static int f81534_port_probe(struct usb_serial_port *port)
 {
+   struct f81534_serial_private *serial_priv;
struct f81534_port_private *port_priv;
int ret;
+   u8 value;
 
+   serial_priv = usb_get_serial_data(port->serial);
port_priv = devm_kzalloc(>dev, sizeof(*port_priv), GFP_KERNEL);
if (!port_priv)
return -ENOMEM;
@@ -1309,6 +1321,24 @@ static int f81534_port_probe(struct usb_serial_port 
*port)
if (ret)
return ret;
 
+   value = serial_priv->conf_data[port_priv->phy_num];
+   switch (value & F81534_UART_MODE_MASK) {
+   case F81534_PORT_CONF_RS485_INVERT:
+   port_priv->shadow_clk |= F81534_CLK_RS485_MODE |
+   F81534_CLK_RS485_INVERT;
+   dev_dbg(>dev, "RS485 invert mode.\n");
+   break;
+   case F81534_PORT_CONF_RS485:
+   port_priv->shadow_clk |= F81534_CLK_RS485_MODE;
+   dev_dbg(>dev, "RS485 mode.\n");
+   break;
+
+   default:
+   case F81534_PORT_CONF_RS232:
+   dev_dbg(>dev, "RS232 mode.\n");
+   break;
+   }
+
return 0;
 }
 
-- 
2.7.4



[PATCH V3 2/6] usb: serial: f81534: add auto RTS direction support

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had auto RTS direction support for RS485 mode.
We'll read it from internal Flash with address 0x2f01~0x2f04 for 4 ports.
There are 4 conditions below:
0: F81534_PORT_CONF_RS232.
1: F81534_PORT_CONF_RS485.
2: value error, default to F81534_PORT_CONF_RS232.
3: F81534_PORT_CONF_RS485_INVERT.

F81532/534 Clock register (offset +08h)

Bit0:   UART Enable (always on)
Bit2-1: Clock source selector
00: 1.846MHz.
01: 18.46MHz.
10: 24MHz.
11: 14.77MHz.
Bit4:   Auto direction(RTS) control (RTS pin Low when TX)
Bit5:   Invert direction(RTS) when Bit4 enabled (RTS pin high when TX)

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: change some BIT() operation to GENMASK().
2: change some dev_info() to dev_dbg().

V2:
1: Read the configure data from flash and save it to shadow clock
   register.

 drivers/usb/serial/f81534.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 1563d3f34381..2201be577dd3 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -98,11 +98,16 @@
 
 #define F81534_DEFAULT_BAUD_RATE   9600
 
+#define F81534_PORT_CONF_RS232 0
+#define F81534_PORT_CONF_RS485 BIT(0)
+#define F81534_PORT_CONF_RS485_INVERT  GENMASK(1, 0)
 #define F81534_PORT_CONF_DISABLE_PORT  BIT(3)
 #define F81534_PORT_CONF_NOT_EXIST_PORTBIT(7)
 #define F81534_PORT_UNAVAILABLE\
(F81534_PORT_CONF_DISABLE_PORT | F81534_PORT_CONF_NOT_EXIST_PORT)
 
+#define F81534_UART_MODE_MASK  GENMASK(1, 0)
+
 #define F81534_1X_RXTRIGGER0xc3
 #define F81534_8X_RXTRIGGER0xcf
 
@@ -115,6 +120,8 @@
  * 01: 18.46MHz.
  * 10: 24MHz.
  * 11: 14.77MHz.
+ * Bit4:   Auto direction(RTS) control (RTS pin Low when TX)
+ * Bit5:   Invert direction(RTS) when Bit4 enabled (RTS pin high when TX)
  */
 
 #define F81534_UART_EN BIT(0)
@@ -123,6 +130,8 @@
 #define F81534_CLK_24_MHZ  BIT(2)
 #define F81534_CLK_14_77_MHZ   GENMASK(2, 1)
 #define F81534_CLK_MASKGENMASK(2, 1)
+#define F81534_CLK_RS485_MODE  BIT(4)
+#define F81534_CLK_RS485_INVERTBIT(5)
 
 static const struct usb_device_id f81534_id_table[] = {
{ USB_DEVICE(FINTEK_VENDOR_ID_1, FINTEK_DEVICE_ID) },
@@ -1274,9 +1283,12 @@ static void f81534_lsr_worker(struct work_struct *work)
 
 static int f81534_port_probe(struct usb_serial_port *port)
 {
+   struct f81534_serial_private *serial_priv;
struct f81534_port_private *port_priv;
int ret;
+   u8 value;
 
+   serial_priv = usb_get_serial_data(port->serial);
port_priv = devm_kzalloc(>dev, sizeof(*port_priv), GFP_KERNEL);
if (!port_priv)
return -ENOMEM;
@@ -1309,6 +1321,24 @@ static int f81534_port_probe(struct usb_serial_port 
*port)
if (ret)
return ret;
 
+   value = serial_priv->conf_data[port_priv->phy_num];
+   switch (value & F81534_UART_MODE_MASK) {
+   case F81534_PORT_CONF_RS485_INVERT:
+   port_priv->shadow_clk |= F81534_CLK_RS485_MODE |
+   F81534_CLK_RS485_INVERT;
+   dev_dbg(>dev, "RS485 invert mode.\n");
+   break;
+   case F81534_PORT_CONF_RS485:
+   port_priv->shadow_clk |= F81534_CLK_RS485_MODE;
+   dev_dbg(>dev, "RS485 mode.\n");
+   break;
+
+   default:
+   case F81534_PORT_CONF_RS232:
+   dev_dbg(>dev, "RS232 mode.\n");
+   break;
+   }
+
return 0;
 }
 
-- 
2.7.4



[PATCH V3 5/6] usb: serial: f81534: add H/W disable port support

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 can be disable port by manufacturer with
following H/W design.
1: Connect DCD/DSR/CTS/RI pin to ground.
2: Connect RX pin to ground.

In driver, we'll implements some detect method likes following:
1: Read MSR.
2: Turn MCR LOOP bit on, off and read LSR after delay with 60ms.
   It'll contain BREAK status in LSR.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: Separate old patch into refacting and H/W disable patches.

V2:
1: f81534_check_port_hw_disabled() change return type from int to bool.
2: Add help function f81534_set_phy_port_register() /
   f81534_get_phy_port_register() for f81534_check_port_hw_disabled()
   to read register without port.
3: Re-write f81534_calc_num_ports() & f81534_attach() to reduce the
   f81534_check_port_hw_disabled() repeatedly called.

 drivers/usb/serial/f81534.c | 81 +
 1 file changed, 81 insertions(+)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index bc0a4bd5dcec..08ef72ea2eec 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -307,6 +307,20 @@ static int f81534_set_mask_register(struct usb_serial 
*serial, u16 reg,
return f81534_set_register(serial, reg, tmp);
 }
 
+static int f81534_set_phy_port_register(struct usb_serial *serial, int phy,
+   u16 reg, u8 data)
+{
+   return f81534_set_register(serial, reg + F81534_UART_OFFSET * phy,
+   data);
+}
+
+static int f81534_get_phy_port_register(struct usb_serial *serial, int phy,
+   u16 reg, u8 *data)
+{
+   return f81534_get_register(serial, reg + F81534_UART_OFFSET * phy,
+   data);
+}
+
 static int f81534_set_port_register(struct usb_serial_port *port, u16 reg,
u8 data)
 {
@@ -733,6 +747,70 @@ static int f81534_find_config_idx(struct usb_serial 
*serial, u8 *index)
 }
 
 /*
+ * The F81532/534 will not report serial port to USB serial subsystem when
+ * H/W DCD/DSR/CTS/RI/RX pin connected to ground.
+ *
+ * To detect RX pin status, we'll enable MCR interal loopback, disable it and
+ * delayed for 60ms. It connected to ground If LSR register report UART_LSR_BI.
+ */
+static bool f81534_check_port_hw_disabled(struct usb_serial *serial, int phy)
+{
+   int status;
+   u8 old_mcr;
+   u8 msr;
+   u8 lsr;
+   u8 msr_mask;
+
+   msr_mask = UART_MSR_DCD | UART_MSR_RI | UART_MSR_DSR | UART_MSR_CTS;
+
+   status = f81534_get_phy_port_register(serial, phy,
+   F81534_MODEM_STATUS_REG, );
+   if (status)
+   return false;
+
+   if ((msr & msr_mask) != msr_mask)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_FIFO_CONTROL_REG, UART_FCR_ENABLE_FIFO |
+   UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+   if (status)
+   return false;
+
+   status = f81534_get_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, _mcr);
+   if (status)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, UART_MCR_LOOP);
+   if (status)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, 0x0);
+   if (status)
+   return false;
+
+   msleep(60);
+
+   status = f81534_get_phy_port_register(serial, phy,
+   F81534_LINE_STATUS_REG, );
+   if (status)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, old_mcr);
+   if (status)
+   return false;
+
+   if ((lsr & UART_LSR_BI) == UART_LSR_BI)
+   return true;
+
+   return false;
+}
+
+/*
  * We had 2 generation of F81532/534 IC. All has an internal storage.
  *
  * 1st is pure USB-to-TTL RS232 IC and designed for 4 ports only, no any
@@ -823,6 +901,9 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
 
/* New style, find all possible ports */
for (i = 0; i < F81534_NUM_PORT; ++i) {
+   if (f81534_check_port_hw_disabled(serial, i))
+   serial_priv->conf_data[i] |= F81534_PORT_UNAVAILABLE;
+
if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
continue;
 
-- 
2.7.4



[PATCH V3 5/6] usb: serial: f81534: add H/W disable port support

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 can be disable port by manufacturer with
following H/W design.
1: Connect DCD/DSR/CTS/RI pin to ground.
2: Connect RX pin to ground.

In driver, we'll implements some detect method likes following:
1: Read MSR.
2: Turn MCR LOOP bit on, off and read LSR after delay with 60ms.
   It'll contain BREAK status in LSR.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: Separate old patch into refacting and H/W disable patches.

V2:
1: f81534_check_port_hw_disabled() change return type from int to bool.
2: Add help function f81534_set_phy_port_register() /
   f81534_get_phy_port_register() for f81534_check_port_hw_disabled()
   to read register without port.
3: Re-write f81534_calc_num_ports() & f81534_attach() to reduce the
   f81534_check_port_hw_disabled() repeatedly called.

 drivers/usb/serial/f81534.c | 81 +
 1 file changed, 81 insertions(+)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index bc0a4bd5dcec..08ef72ea2eec 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -307,6 +307,20 @@ static int f81534_set_mask_register(struct usb_serial 
*serial, u16 reg,
return f81534_set_register(serial, reg, tmp);
 }
 
+static int f81534_set_phy_port_register(struct usb_serial *serial, int phy,
+   u16 reg, u8 data)
+{
+   return f81534_set_register(serial, reg + F81534_UART_OFFSET * phy,
+   data);
+}
+
+static int f81534_get_phy_port_register(struct usb_serial *serial, int phy,
+   u16 reg, u8 *data)
+{
+   return f81534_get_register(serial, reg + F81534_UART_OFFSET * phy,
+   data);
+}
+
 static int f81534_set_port_register(struct usb_serial_port *port, u16 reg,
u8 data)
 {
@@ -733,6 +747,70 @@ static int f81534_find_config_idx(struct usb_serial 
*serial, u8 *index)
 }
 
 /*
+ * The F81532/534 will not report serial port to USB serial subsystem when
+ * H/W DCD/DSR/CTS/RI/RX pin connected to ground.
+ *
+ * To detect RX pin status, we'll enable MCR interal loopback, disable it and
+ * delayed for 60ms. It connected to ground If LSR register report UART_LSR_BI.
+ */
+static bool f81534_check_port_hw_disabled(struct usb_serial *serial, int phy)
+{
+   int status;
+   u8 old_mcr;
+   u8 msr;
+   u8 lsr;
+   u8 msr_mask;
+
+   msr_mask = UART_MSR_DCD | UART_MSR_RI | UART_MSR_DSR | UART_MSR_CTS;
+
+   status = f81534_get_phy_port_register(serial, phy,
+   F81534_MODEM_STATUS_REG, );
+   if (status)
+   return false;
+
+   if ((msr & msr_mask) != msr_mask)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_FIFO_CONTROL_REG, UART_FCR_ENABLE_FIFO |
+   UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+   if (status)
+   return false;
+
+   status = f81534_get_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, _mcr);
+   if (status)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, UART_MCR_LOOP);
+   if (status)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, 0x0);
+   if (status)
+   return false;
+
+   msleep(60);
+
+   status = f81534_get_phy_port_register(serial, phy,
+   F81534_LINE_STATUS_REG, );
+   if (status)
+   return false;
+
+   status = f81534_set_phy_port_register(serial, phy,
+   F81534_MODEM_CONTROL_REG, old_mcr);
+   if (status)
+   return false;
+
+   if ((lsr & UART_LSR_BI) == UART_LSR_BI)
+   return true;
+
+   return false;
+}
+
+/*
  * We had 2 generation of F81532/534 IC. All has an internal storage.
  *
  * 1st is pure USB-to-TTL RS232 IC and designed for 4 ports only, no any
@@ -823,6 +901,9 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
 
/* New style, find all possible ports */
for (i = 0; i < F81534_NUM_PORT; ++i) {
+   if (f81534_check_port_hw_disabled(serial, i))
+   serial_priv->conf_data[i] |= F81534_PORT_UNAVAILABLE;
+
if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
continue;
 
-- 
2.7.4



[PATCH V3 4/6] usb: serial: f81534: refactoring calc_num_ports()

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
In the original code, We'll read configuration in calc_num_ports()
and read again in attach(). In fact, we can move all content from
attach() to calc_num_ports() to simplify the code.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: First introduced in this series patches.

 drivers/usb/serial/f81534.c | 116 
 1 file changed, 31 insertions(+), 85 deletions(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index e7dd01310f20..bc0a4bd5dcec 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -753,14 +753,14 @@ static int f81534_find_config_idx(struct usb_serial 
*serial, u8 *index)
 static int f81534_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
 {
+   struct f81534_serial_private *serial_priv;
struct device *dev = >interface->dev;
int size_bulk_in = usb_endpoint_maxp(epds->bulk_in[0]);
int size_bulk_out = usb_endpoint_maxp(epds->bulk_out[0]);
-   u8 setting[F81534_CUSTOM_DATA_SIZE];
-   u8 setting_idx;
u8 num_port = 0;
+   int index = 0;
int status;
-   size_t i;
+   int i;
 
if (size_bulk_out != F81534_WRITE_BUFFER_SIZE ||
size_bulk_in != F81534_MAX_RECEIVE_BLOCK_SIZE) {
@@ -768,8 +768,16 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
return -ENODEV;
}
 
+   serial_priv = devm_kzalloc(>interface->dev,
+   sizeof(*serial_priv), GFP_KERNEL);
+   if (!serial_priv)
+   return -ENOMEM;
+
+   usb_set_serial_data(serial, serial_priv);
+   mutex_init(_priv->urb_mutex);
+
/* Check had custom setting */
-   status = f81534_find_config_idx(serial, _idx);
+   status = f81534_find_config_idx(serial, _priv->setting_idx);
if (status) {
dev_err(>interface->dev, "%s: find idx failed: %d\n",
__func__, status);
@@ -780,11 +788,12 @@ static int f81534_calc_num_ports(struct usb_serial 
*serial,
 * We'll read custom data only when data available, otherwise we'll
 * read default value instead.
 */
-   if (setting_idx != F81534_CUSTOM_NO_CUSTOM_DATA) {
+   if (serial_priv->setting_idx != F81534_CUSTOM_NO_CUSTOM_DATA) {
status = f81534_read_flash(serial,
F81534_CUSTOM_ADDRESS_START +
F81534_CONF_OFFSET,
-   sizeof(setting), setting);
+   sizeof(serial_priv->conf_data),
+   serial_priv->conf_data);
if (status) {
dev_err(>interface->dev,
"%s: get custom data failed: %d\n",
@@ -794,13 +803,13 @@ static int f81534_calc_num_ports(struct usb_serial 
*serial,
 
dev_dbg(>interface->dev,
"%s: read config from block: %d\n", __func__,
-   setting_idx);
+   serial_priv->setting_idx);
} else {
/* Read default board setting */
status = f81534_read_flash(serial,
-   F81534_DEF_CONF_ADDRESS_START, F81534_NUM_PORT,
-   setting);
-
+   F81534_DEF_CONF_ADDRESS_START,
+   sizeof(serial_priv->conf_data),
+   serial_priv->conf_data);
if (status) {
dev_err(>interface->dev,
"%s: read failed: %d\n", __func__,
@@ -814,7 +823,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
 
/* New style, find all possible ports */
for (i = 0; i < F81534_NUM_PORT; ++i) {
-   if (setting[i] & F81534_PORT_UNAVAILABLE)
+   if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
continue;
 
++num_port;
@@ -826,6 +835,17 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
num_port = 4;   /* Nothing found, oldest version IC */
}
 
+   /* Assign phy-to-logic mapping */
+   for (i = 0; i < F81534_NUM_PORT; ++i) {
+   if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
+   continue;
+
+   serial_priv->tty_idx[i] = index++;
+   dev_dbg(>interface->dev,
+   "%s: phy_num: %d, tty_idx: %d\n", __func__, i,
+   serial_priv->tty_idx[i]);
+   }
+
/*
 * Setup bulk-out endpoint multiplexing. All ports share the same
 * bulk-out 

[PATCH V3 4/6] usb: serial: f81534: refactoring calc_num_ports()

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
In the original code, We'll read configuration in calc_num_ports()
and read again in attach(). In fact, we can move all content from
attach() to calc_num_ports() to simplify the code.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: First introduced in this series patches.

 drivers/usb/serial/f81534.c | 116 
 1 file changed, 31 insertions(+), 85 deletions(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index e7dd01310f20..bc0a4bd5dcec 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -753,14 +753,14 @@ static int f81534_find_config_idx(struct usb_serial 
*serial, u8 *index)
 static int f81534_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
 {
+   struct f81534_serial_private *serial_priv;
struct device *dev = >interface->dev;
int size_bulk_in = usb_endpoint_maxp(epds->bulk_in[0]);
int size_bulk_out = usb_endpoint_maxp(epds->bulk_out[0]);
-   u8 setting[F81534_CUSTOM_DATA_SIZE];
-   u8 setting_idx;
u8 num_port = 0;
+   int index = 0;
int status;
-   size_t i;
+   int i;
 
if (size_bulk_out != F81534_WRITE_BUFFER_SIZE ||
size_bulk_in != F81534_MAX_RECEIVE_BLOCK_SIZE) {
@@ -768,8 +768,16 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
return -ENODEV;
}
 
+   serial_priv = devm_kzalloc(>interface->dev,
+   sizeof(*serial_priv), GFP_KERNEL);
+   if (!serial_priv)
+   return -ENOMEM;
+
+   usb_set_serial_data(serial, serial_priv);
+   mutex_init(_priv->urb_mutex);
+
/* Check had custom setting */
-   status = f81534_find_config_idx(serial, _idx);
+   status = f81534_find_config_idx(serial, _priv->setting_idx);
if (status) {
dev_err(>interface->dev, "%s: find idx failed: %d\n",
__func__, status);
@@ -780,11 +788,12 @@ static int f81534_calc_num_ports(struct usb_serial 
*serial,
 * We'll read custom data only when data available, otherwise we'll
 * read default value instead.
 */
-   if (setting_idx != F81534_CUSTOM_NO_CUSTOM_DATA) {
+   if (serial_priv->setting_idx != F81534_CUSTOM_NO_CUSTOM_DATA) {
status = f81534_read_flash(serial,
F81534_CUSTOM_ADDRESS_START +
F81534_CONF_OFFSET,
-   sizeof(setting), setting);
+   sizeof(serial_priv->conf_data),
+   serial_priv->conf_data);
if (status) {
dev_err(>interface->dev,
"%s: get custom data failed: %d\n",
@@ -794,13 +803,13 @@ static int f81534_calc_num_ports(struct usb_serial 
*serial,
 
dev_dbg(>interface->dev,
"%s: read config from block: %d\n", __func__,
-   setting_idx);
+   serial_priv->setting_idx);
} else {
/* Read default board setting */
status = f81534_read_flash(serial,
-   F81534_DEF_CONF_ADDRESS_START, F81534_NUM_PORT,
-   setting);
-
+   F81534_DEF_CONF_ADDRESS_START,
+   sizeof(serial_priv->conf_data),
+   serial_priv->conf_data);
if (status) {
dev_err(>interface->dev,
"%s: read failed: %d\n", __func__,
@@ -814,7 +823,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
 
/* New style, find all possible ports */
for (i = 0; i < F81534_NUM_PORT; ++i) {
-   if (setting[i] & F81534_PORT_UNAVAILABLE)
+   if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
continue;
 
++num_port;
@@ -826,6 +835,17 @@ static int f81534_calc_num_ports(struct usb_serial *serial,
num_port = 4;   /* Nothing found, oldest version IC */
}
 
+   /* Assign phy-to-logic mapping */
+   for (i = 0; i < F81534_NUM_PORT; ++i) {
+   if (serial_priv->conf_data[i] & F81534_PORT_UNAVAILABLE)
+   continue;
+
+   serial_priv->tty_idx[i] = index++;
+   dev_dbg(>interface->dev,
+   "%s: phy_num: %d, tty_idx: %d\n", __func__, i,
+   serial_priv->tty_idx[i]);
+   }
+
/*
 * Setup bulk-out endpoint multiplexing. All ports share the same
 * bulk-out endpoint.
@@ -1227,79 +1247,6 

[PATCH V3 1/6] usb: serial: f81534: add high baud rate support

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had 4 clocksource 1.846/18.46/14.77/24MHz and baud rates
can be up to 1.5Mbits with 24MHz.

This device may generate data overrun when baud rate setting to 921600bps
or higher with old UART trigger level setting (8x14=112) with full
loading. We'll change trigger level from 8x14=112 to 8x8=64 to avoid data
overrun.

Also the read/write of EP0 will be affected by this patch. The worst case
of responding time is 20s when all serial port are full loading and trying
to access EP0, so we change EP0 timeout from 10 to 20s.

F81532/534 Clock register (offset +08h)

Bit0:   UART Enable (always on)
Bit2-1: Clock source selector
00: 1.846MHz.
01: 18.46MHz.
10: 24MHz.
11: 14.77MHz.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: Separate UART Enable bit from clock sources and active it in
   port_probe() with port_priv->shadow_clk.
2: Add sanity check for clocksource idx in set_port_config().
3: change calc_baud_divisor() parameter from F81534_MAX_BAUDRATE
   to priv->baud_base.

v2:
1: Add commit message for F81534_USB_TIMEOUT from 1000 to 2000 and
   trigger level from UART_FCR_R_TRIG_11 to UART_FCR_TRIGGER_8.
2: Separate UART Enable bit from clock sources.
3: Add help function "f81534_find_clk()" to calculate baud rate and
   clock source
4: Add shadow clock register for future use. 

 drivers/usb/serial/f81534.c | 93 +
 1 file changed, 77 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index e4573b4c8935..1563d3f34381 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -41,6 +41,7 @@
 #define F81534_MODEM_CONTROL_REG   (0x04 + F81534_UART_BASE_ADDRESS)
 #define F81534_LINE_STATUS_REG (0x05 + F81534_UART_BASE_ADDRESS)
 #define F81534_MODEM_STATUS_REG(0x06 + 
F81534_UART_BASE_ADDRESS)
+#define F81534_CLOCK_REG   (0x08 + F81534_UART_BASE_ADDRESS)
 #define F81534_CONFIG1_REG (0x09 + F81534_UART_BASE_ADDRESS)
 
 #define F81534_DEF_CONF_ADDRESS_START  0x3000
@@ -57,7 +58,7 @@
 
 /* Default URB timeout for USB operations */
 #define F81534_USB_MAX_RETRY   10
-#define F81534_USB_TIMEOUT 1000
+#define F81534_USB_TIMEOUT 2000
 #define F81534_SET_GET_REGISTER0xA0
 
 #define F81534_NUM_PORT4
@@ -96,7 +97,6 @@
 #define F81534_CMD_READ0x03
 
 #define F81534_DEFAULT_BAUD_RATE   9600
-#define F81534_MAX_BAUDRATE115200
 
 #define F81534_PORT_CONF_DISABLE_PORT  BIT(3)
 #define F81534_PORT_CONF_NOT_EXIST_PORTBIT(7)
@@ -106,6 +106,24 @@
 #define F81534_1X_RXTRIGGER0xc3
 #define F81534_8X_RXTRIGGER0xcf
 
+/*
+ * F81532/534 Clock registers (offset +08h)
+ *
+ * Bit0:   UART Enable (always on)
+ * Bit2-1: Clock source selector
+ * 00: 1.846MHz.
+ * 01: 18.46MHz.
+ * 10: 24MHz.
+ * 11: 14.77MHz.
+ */
+
+#define F81534_UART_EN BIT(0)
+#define F81534_CLK_1_846_MHZ   0
+#define F81534_CLK_18_46_MHZ   BIT(1)
+#define F81534_CLK_24_MHZ  BIT(2)
+#define F81534_CLK_14_77_MHZ   GENMASK(2, 1)
+#define F81534_CLK_MASKGENMASK(2, 1)
+
 static const struct usb_device_id f81534_id_table[] = {
{ USB_DEVICE(FINTEK_VENDOR_ID_1, FINTEK_DEVICE_ID) },
{ USB_DEVICE(FINTEK_VENDOR_ID_2, FINTEK_DEVICE_ID) },
@@ -129,12 +147,18 @@ struct f81534_port_private {
struct usb_serial_port *port;
unsigned long tx_empty;
spinlock_t msr_lock;
+   u32 baud_base;
u8 shadow_mcr;
u8 shadow_lcr;
u8 shadow_msr;
+   u8 shadow_clk;
u8 phy_num;
 };
 
+static u32 const baudrate_table[] = { 115200, 921600, 1152000, 150 };
+static u8 const clock_table[] = { F81534_CLK_1_846_MHZ, F81534_CLK_14_77_MHZ,
+   F81534_CLK_18_46_MHZ, F81534_CLK_24_MHZ };
+
 static int f81534_logic_to_phy_port(struct usb_serial *serial,
struct usb_serial_port *port)
 {
@@ -460,13 +484,52 @@ static u32 f81534_calc_baud_divisor(u32 baudrate, u32 
clockrate)
return DIV_ROUND_CLOSEST(clockrate, baudrate);
 }
 
-static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
-   u8 lcr)
+static int f81534_find_clk(u32 baudrate)
+{
+   int idx;
+
+   for (idx = 0; idx < ARRAY_SIZE(baudrate_table); ++idx) {
+   if (baudrate <= baudrate_table[idx] &&
+   baudrate_table[idx] % baudrate == 0)
+   return idx;
+   }
+
+   return 

[PATCH v2 04/16] ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro

2018-01-10 Thread Nicolin Chen
The define of fsl_ssi_disable_val is not so clear as it mixes two
steps of calculations together. And those parameter names are also
a bit long to read.

Since it just tries to exclude the shared bits from the regvals of
current stream while the opposite stream is active, it's better to
use something like ssi_excl_shared_bits.

This patch also bisects fsl_ssi_disable_val into two macros of two
corresponding steps and then shortens its parameter names. It also
updates callers in the fsl_ssi_config() accordingly.

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index aa14a5d..f026386 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -417,24 +417,24 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 }
 
 /**
- * Calculate the bits that have to be disabled for the current stream that is
- * getting disabled. This keeps the bits enabled that are necessary for the
- * second stream to work if 'stream_active' is true.
+ * Exclude bits that are used by the opposite stream
  *
- * Detailed calculation:
- * These are the values that need to be active after disabling. For non-active
- * second stream, this is 0:
- * vals_stream * !!stream_active
+ * When both streams are active, disabling some bits for the current stream
+ * might break the other stream if these bits are used by it.
  *
- * The following computes the overall differences between the setup for the
- * to-disable stream and the active stream, a simple XOR:
- * vals_disable ^ (vals_stream * !!(stream_active))
+ * @vals : regvals of the current stream
+ * @avals: regvals of the opposite stream
+ * @aactive: active state of the opposite stream
  *
- * The full expression adds a mask on all values we care about
+ *  1) XOR vals and avals to get the differences if the other stream is active;
+ * Otherwise, return current vals if the other stream is not active
+ *  2) AND the result of 1) with the current vals
  */
-#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
-   ((vals_disable) & \
-((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active
+#define _ssi_xor_shared_bits(vals, avals, aactive) \
+   ((vals) ^ ((avals) * (aactive)))
+
+#define ssi_excl_shared_bits(vals, avals, aactive) \
+   ((vals) & _ssi_xor_shared_bits(vals, avals, aactive))
 
 /**
  * Enable or disable SSI configuration.
@@ -445,16 +445,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
bool dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
-   int nr_active_streams;
-   int keep_active;
-
-   nr_active_streams = !!(ssi->streams & BIT(TX)) +
-   !!(ssi->streams & BIT(RX));
+   bool aactive;
 
-   if (nr_active_streams - 1 > 0)
-   keep_active = 1;
-   else
-   keep_active = 0;
+   /* Check if the opposite stream is active */
+   aactive = ssi->streams & BIT(!dir);
 
/* Get the opposite direction to keep its values untouched */
if (>regvals[RX] == vals)
@@ -467,8 +461,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
- keep_active);
+   u32 scr = ssi_excl_shared_bits(vals->scr, avals->scr, aactive);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
 
@@ -483,7 +476,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * 2) Disable all remaining bits of both streams when last stream ends
 */
if (ssi->soc->offline_config) {
-   if ((enable && !nr_active_streams) || (!enable && !keep_active))
+   if ((enable && !ssi->streams) || (!enable && !aactive))
fsl_ssi_rxtx_config(ssi, enable);
 
goto config_done;
@@ -505,12 +498,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   sier = fsl_ssi_disable_val(vals->sier, avals->sier,
-  keep_active);
-   srcr = fsl_ssi_disable_val(vals->srcr, avals->srcr,
-  keep_active);
-   stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
- 

Re: [RFC PATCH v2 5/6] x86/entry/pti: avoid setting CR3 when it's already correct

2018-01-10 Thread Willy Tarreau
On Wed, Jan 10, 2018 at 12:29:17PM -0800, Dave Hansen wrote:
> On 01/09/2018 04:56 AM, Willy Tarreau wrote:
> > --- a/arch/x86/entry/calling.h
> > +++ b/arch/x86/entry/calling.h
> > @@ -214,6 +214,11 @@
> >  .macro SWITCH_TO_KERNEL_CR3 scratch_reg:req
> > ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
> > mov %cr3, \scratch_reg
> > +
> > +   /* if we're already on the kernel PGD, we don't switch */
> > +   testq $(PTI_SWITCH_PGTABLES_MASK), \scratch_reg
> > +   jz .Lend_\@
> > +
> > ADJUST_KERNEL_CR3 \scratch_reg
> 
> Willy, this is not specific to your patch, but it is one of the first
> *changes* to this code since Spectre, thus I'm bringing it up in this
> thread.
> 
> The code already has some, but new conditional branches give me the
> willies.  None of them take the form that can be used to exploit
> Spectre/Variant1 that I can see, but I do think we need to start talking
> about why this is not vulnerable and probably documenting it in the
> entry code.
> 
> Spectre/V1 (conditional branches)
>  * Data reads in entry/exit when you have the user CR3 must be in
>cpu_entry_area and readable to a Meltdown exploit, anyway.  That
>implies that there is no data to be leaked in the address space
>at all at this point.
>  * Conditional branches in the entry/exit code with a kernel CR3 value
>are the only concern.  It is safe, however, if the data being checked
>is not user-controllable.
> 
> Spectre/V2 (indirect branches)
>  * Indirect Branches in the entry code are forbidden because of
>Spectre/V2.  Retpolines or other mitigations (IBRS) must be used
>instead.
> 
> Anybody disagree?
> 
> In this case, the data being checked (CR3) is not user-controllable and
> there are no indirect branches.  So this code is OK.

Just let me know what comment you'd like me to add there. I suppose
something like "This code has code has been checked against Spectre/v1/v2
attacks ; it's safe as CR3 is not user-controllable and there's no
indirect branches" ?

Thanks,
Willy


[PATCH V3 6/6] usb: serial: f81534: fix tx error on some baud rate

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had 4 clocksource 1.846/18.46/14.77/24MHz and baud rates
can be up to 1.5Mbits with 24MHz. But on some baud rate (384~500kps), the
TX side will send the data frame too close to treat frame error on RX
side. This patch will force all TX data frame with delay 1bit gap.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: had not noticeable changes.

V2:
1: First introduced in this series patches.

 drivers/usb/serial/f81534.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 08ef72ea2eec..92c9d8f18a5a 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -131,6 +131,8 @@
 #define F81534_CLK_24_MHZ  BIT(2)
 #define F81534_CLK_14_77_MHZ   GENMASK(2, 1)
 #define F81534_CLK_MASKGENMASK(2, 1)
+#define F81534_CLK_TX_DELAY_1BIT   BIT(3)
+
 #define F81534_CLK_RS485_MODE  BIT(4)
 #define F81534_CLK_RS485_INVERTBIT(5)
 
@@ -1386,7 +1388,11 @@ static int f81534_port_probe(struct usb_serial_port 
*port)
if (!port_priv)
return -ENOMEM;
 
-   port_priv->shadow_clk = F81534_UART_EN;
+   /*
+* We'll make tx frame error when baud rate from 384~500kps. So we'll
+* delay all tx data frame with 1bit.
+*/
+   port_priv->shadow_clk = F81534_UART_EN | F81534_CLK_TX_DELAY_1BIT;
spin_lock_init(_priv->msr_lock);
mutex_init(_priv->mcr_mutex);
mutex_init(_priv->lcr_mutex);
-- 
2.7.4



[PATCH V3 1/6] usb: serial: f81534: add high baud rate support

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had 4 clocksource 1.846/18.46/14.77/24MHz and baud rates
can be up to 1.5Mbits with 24MHz.

This device may generate data overrun when baud rate setting to 921600bps
or higher with old UART trigger level setting (8x14=112) with full
loading. We'll change trigger level from 8x14=112 to 8x8=64 to avoid data
overrun.

Also the read/write of EP0 will be affected by this patch. The worst case
of responding time is 20s when all serial port are full loading and trying
to access EP0, so we change EP0 timeout from 10 to 20s.

F81532/534 Clock register (offset +08h)

Bit0:   UART Enable (always on)
Bit2-1: Clock source selector
00: 1.846MHz.
01: 18.46MHz.
10: 24MHz.
11: 14.77MHz.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: Separate UART Enable bit from clock sources and active it in
   port_probe() with port_priv->shadow_clk.
2: Add sanity check for clocksource idx in set_port_config().
3: change calc_baud_divisor() parameter from F81534_MAX_BAUDRATE
   to priv->baud_base.

v2:
1: Add commit message for F81534_USB_TIMEOUT from 1000 to 2000 and
   trigger level from UART_FCR_R_TRIG_11 to UART_FCR_TRIGGER_8.
2: Separate UART Enable bit from clock sources.
3: Add help function "f81534_find_clk()" to calculate baud rate and
   clock source
4: Add shadow clock register for future use. 

 drivers/usb/serial/f81534.c | 93 +
 1 file changed, 77 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index e4573b4c8935..1563d3f34381 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -41,6 +41,7 @@
 #define F81534_MODEM_CONTROL_REG   (0x04 + F81534_UART_BASE_ADDRESS)
 #define F81534_LINE_STATUS_REG (0x05 + F81534_UART_BASE_ADDRESS)
 #define F81534_MODEM_STATUS_REG(0x06 + 
F81534_UART_BASE_ADDRESS)
+#define F81534_CLOCK_REG   (0x08 + F81534_UART_BASE_ADDRESS)
 #define F81534_CONFIG1_REG (0x09 + F81534_UART_BASE_ADDRESS)
 
 #define F81534_DEF_CONF_ADDRESS_START  0x3000
@@ -57,7 +58,7 @@
 
 /* Default URB timeout for USB operations */
 #define F81534_USB_MAX_RETRY   10
-#define F81534_USB_TIMEOUT 1000
+#define F81534_USB_TIMEOUT 2000
 #define F81534_SET_GET_REGISTER0xA0
 
 #define F81534_NUM_PORT4
@@ -96,7 +97,6 @@
 #define F81534_CMD_READ0x03
 
 #define F81534_DEFAULT_BAUD_RATE   9600
-#define F81534_MAX_BAUDRATE115200
 
 #define F81534_PORT_CONF_DISABLE_PORT  BIT(3)
 #define F81534_PORT_CONF_NOT_EXIST_PORTBIT(7)
@@ -106,6 +106,24 @@
 #define F81534_1X_RXTRIGGER0xc3
 #define F81534_8X_RXTRIGGER0xcf
 
+/*
+ * F81532/534 Clock registers (offset +08h)
+ *
+ * Bit0:   UART Enable (always on)
+ * Bit2-1: Clock source selector
+ * 00: 1.846MHz.
+ * 01: 18.46MHz.
+ * 10: 24MHz.
+ * 11: 14.77MHz.
+ */
+
+#define F81534_UART_EN BIT(0)
+#define F81534_CLK_1_846_MHZ   0
+#define F81534_CLK_18_46_MHZ   BIT(1)
+#define F81534_CLK_24_MHZ  BIT(2)
+#define F81534_CLK_14_77_MHZ   GENMASK(2, 1)
+#define F81534_CLK_MASKGENMASK(2, 1)
+
 static const struct usb_device_id f81534_id_table[] = {
{ USB_DEVICE(FINTEK_VENDOR_ID_1, FINTEK_DEVICE_ID) },
{ USB_DEVICE(FINTEK_VENDOR_ID_2, FINTEK_DEVICE_ID) },
@@ -129,12 +147,18 @@ struct f81534_port_private {
struct usb_serial_port *port;
unsigned long tx_empty;
spinlock_t msr_lock;
+   u32 baud_base;
u8 shadow_mcr;
u8 shadow_lcr;
u8 shadow_msr;
+   u8 shadow_clk;
u8 phy_num;
 };
 
+static u32 const baudrate_table[] = { 115200, 921600, 1152000, 150 };
+static u8 const clock_table[] = { F81534_CLK_1_846_MHZ, F81534_CLK_14_77_MHZ,
+   F81534_CLK_18_46_MHZ, F81534_CLK_24_MHZ };
+
 static int f81534_logic_to_phy_port(struct usb_serial *serial,
struct usb_serial_port *port)
 {
@@ -460,13 +484,52 @@ static u32 f81534_calc_baud_divisor(u32 baudrate, u32 
clockrate)
return DIV_ROUND_CLOSEST(clockrate, baudrate);
 }
 
-static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
-   u8 lcr)
+static int f81534_find_clk(u32 baudrate)
+{
+   int idx;
+
+   for (idx = 0; idx < ARRAY_SIZE(baudrate_table); ++idx) {
+   if (baudrate <= baudrate_table[idx] &&
+   baudrate_table[idx] % baudrate == 0)
+   return idx;
+   }
+
+   return -EINVAL;
+}
+
+static int 

[PATCH v2 04/16] ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro

2018-01-10 Thread Nicolin Chen
The define of fsl_ssi_disable_val is not so clear as it mixes two
steps of calculations together. And those parameter names are also
a bit long to read.

Since it just tries to exclude the shared bits from the regvals of
current stream while the opposite stream is active, it's better to
use something like ssi_excl_shared_bits.

This patch also bisects fsl_ssi_disable_val into two macros of two
corresponding steps and then shortens its parameter names. It also
updates callers in the fsl_ssi_config() accordingly.

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index aa14a5d..f026386 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -417,24 +417,24 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 }
 
 /**
- * Calculate the bits that have to be disabled for the current stream that is
- * getting disabled. This keeps the bits enabled that are necessary for the
- * second stream to work if 'stream_active' is true.
+ * Exclude bits that are used by the opposite stream
  *
- * Detailed calculation:
- * These are the values that need to be active after disabling. For non-active
- * second stream, this is 0:
- * vals_stream * !!stream_active
+ * When both streams are active, disabling some bits for the current stream
+ * might break the other stream if these bits are used by it.
  *
- * The following computes the overall differences between the setup for the
- * to-disable stream and the active stream, a simple XOR:
- * vals_disable ^ (vals_stream * !!(stream_active))
+ * @vals : regvals of the current stream
+ * @avals: regvals of the opposite stream
+ * @aactive: active state of the opposite stream
  *
- * The full expression adds a mask on all values we care about
+ *  1) XOR vals and avals to get the differences if the other stream is active;
+ * Otherwise, return current vals if the other stream is not active
+ *  2) AND the result of 1) with the current vals
  */
-#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
-   ((vals_disable) & \
-((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active
+#define _ssi_xor_shared_bits(vals, avals, aactive) \
+   ((vals) ^ ((avals) * (aactive)))
+
+#define ssi_excl_shared_bits(vals, avals, aactive) \
+   ((vals) & _ssi_xor_shared_bits(vals, avals, aactive))
 
 /**
  * Enable or disable SSI configuration.
@@ -445,16 +445,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
bool dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
-   int nr_active_streams;
-   int keep_active;
-
-   nr_active_streams = !!(ssi->streams & BIT(TX)) +
-   !!(ssi->streams & BIT(RX));
+   bool aactive;
 
-   if (nr_active_streams - 1 > 0)
-   keep_active = 1;
-   else
-   keep_active = 0;
+   /* Check if the opposite stream is active */
+   aactive = ssi->streams & BIT(!dir);
 
/* Get the opposite direction to keep its values untouched */
if (>regvals[RX] == vals)
@@ -467,8 +461,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
- keep_active);
+   u32 scr = ssi_excl_shared_bits(vals->scr, avals->scr, aactive);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
 
@@ -483,7 +476,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * 2) Disable all remaining bits of both streams when last stream ends
 */
if (ssi->soc->offline_config) {
-   if ((enable && !nr_active_streams) || (!enable && !keep_active))
+   if ((enable && !ssi->streams) || (!enable && !aactive))
fsl_ssi_rxtx_config(ssi, enable);
 
goto config_done;
@@ -505,12 +498,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   sier = fsl_ssi_disable_val(vals->sier, avals->sier,
-  keep_active);
-   srcr = fsl_ssi_disable_val(vals->srcr, avals->srcr,
-  keep_active);
-   stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
-  

Re: [RFC PATCH v2 5/6] x86/entry/pti: avoid setting CR3 when it's already correct

2018-01-10 Thread Willy Tarreau
On Wed, Jan 10, 2018 at 12:29:17PM -0800, Dave Hansen wrote:
> On 01/09/2018 04:56 AM, Willy Tarreau wrote:
> > --- a/arch/x86/entry/calling.h
> > +++ b/arch/x86/entry/calling.h
> > @@ -214,6 +214,11 @@
> >  .macro SWITCH_TO_KERNEL_CR3 scratch_reg:req
> > ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
> > mov %cr3, \scratch_reg
> > +
> > +   /* if we're already on the kernel PGD, we don't switch */
> > +   testq $(PTI_SWITCH_PGTABLES_MASK), \scratch_reg
> > +   jz .Lend_\@
> > +
> > ADJUST_KERNEL_CR3 \scratch_reg
> 
> Willy, this is not specific to your patch, but it is one of the first
> *changes* to this code since Spectre, thus I'm bringing it up in this
> thread.
> 
> The code already has some, but new conditional branches give me the
> willies.  None of them take the form that can be used to exploit
> Spectre/Variant1 that I can see, but I do think we need to start talking
> about why this is not vulnerable and probably documenting it in the
> entry code.
> 
> Spectre/V1 (conditional branches)
>  * Data reads in entry/exit when you have the user CR3 must be in
>cpu_entry_area and readable to a Meltdown exploit, anyway.  That
>implies that there is no data to be leaked in the address space
>at all at this point.
>  * Conditional branches in the entry/exit code with a kernel CR3 value
>are the only concern.  It is safe, however, if the data being checked
>is not user-controllable.
> 
> Spectre/V2 (indirect branches)
>  * Indirect Branches in the entry code are forbidden because of
>Spectre/V2.  Retpolines or other mitigations (IBRS) must be used
>instead.
> 
> Anybody disagree?
> 
> In this case, the data being checked (CR3) is not user-controllable and
> there are no indirect branches.  So this code is OK.

Just let me know what comment you'd like me to add there. I suppose
something like "This code has code has been checked against Spectre/v1/v2
attacks ; it's safe as CR3 is not user-controllable and there's no
indirect branches" ?

Thanks,
Willy


[PATCH V3 6/6] usb: serial: f81534: fix tx error on some baud rate

2018-01-10 Thread Ji-Ze Hong (Peter Hong)
The F81532/534 had 4 clocksource 1.846/18.46/14.77/24MHz and baud rates
can be up to 1.5Mbits with 24MHz. But on some baud rate (384~500kps), the
TX side will send the data frame too close to treat frame error on RX
side. This patch will force all TX data frame with delay 1bit gap.

Signed-off-by: Ji-Ze Hong (Peter Hong) 
---
V3:
1: had not noticeable changes.

V2:
1: First introduced in this series patches.

 drivers/usb/serial/f81534.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 08ef72ea2eec..92c9d8f18a5a 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -131,6 +131,8 @@
 #define F81534_CLK_24_MHZ  BIT(2)
 #define F81534_CLK_14_77_MHZ   GENMASK(2, 1)
 #define F81534_CLK_MASKGENMASK(2, 1)
+#define F81534_CLK_TX_DELAY_1BIT   BIT(3)
+
 #define F81534_CLK_RS485_MODE  BIT(4)
 #define F81534_CLK_RS485_INVERTBIT(5)
 
@@ -1386,7 +1388,11 @@ static int f81534_port_probe(struct usb_serial_port 
*port)
if (!port_priv)
return -ENOMEM;
 
-   port_priv->shadow_clk = F81534_UART_EN;
+   /*
+* We'll make tx frame error when baud rate from 384~500kps. So we'll
+* delay all tx data frame with 1bit.
+*/
+   port_priv->shadow_clk = F81534_UART_EN | F81534_CLK_TX_DELAY_1BIT;
spin_lock_init(_priv->msr_lock);
mutex_init(_priv->mcr_mutex);
mutex_init(_priv->lcr_mutex);
-- 
2.7.4



[PATCH v2 09/16] ASoC: fsl_ssi: Set xFEN0 and xFEN1 together

2018-01-10 Thread Nicolin Chen
It'd be safer to enable both FIFOs for TX or RX at the same time.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 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 4399a22..e75b57d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -586,6 +586,11 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
if (fsl_ssi_is_ac97(ssi))
vals[RX].scr = vals[TX].scr = 0;
 
+   if (ssi->use_dual_fifo) {
+   vals[RX].srcr |= SSI_SRCR_RFEN1;
+   vals[TX].stcr |= SSI_STCR_TFEN1;
+   }
+
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
vals[TX].sier |= SSI_SIER_TDMAE;
@@ -986,14 +991,9 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
 SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
 
-   if (ssi->use_dual_fifo) {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  SSI_SRCR_RFEN1, SSI_SRCR_RFEN1);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  SSI_STCR_TFEN1, SSI_STCR_TFEN1);
+   if (ssi->use_dual_fifo)
regmap_update_bits(regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-   }
 
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
-- 
2.7.4



[PATCH v2 09/16] ASoC: fsl_ssi: Set xFEN0 and xFEN1 together

2018-01-10 Thread Nicolin Chen
It'd be safer to enable both FIFOs for TX or RX at the same time.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 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 4399a22..e75b57d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -586,6 +586,11 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
if (fsl_ssi_is_ac97(ssi))
vals[RX].scr = vals[TX].scr = 0;
 
+   if (ssi->use_dual_fifo) {
+   vals[RX].srcr |= SSI_SRCR_RFEN1;
+   vals[TX].stcr |= SSI_STCR_TFEN1;
+   }
+
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
vals[TX].sier |= SSI_SIER_TDMAE;
@@ -986,14 +991,9 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
 SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
 
-   if (ssi->use_dual_fifo) {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  SSI_SRCR_RFEN1, SSI_SRCR_RFEN1);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  SSI_STCR_TFEN1, SSI_STCR_TFEN1);
+   if (ssi->use_dual_fifo)
regmap_update_bits(regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-   }
 
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
-- 
2.7.4



[PATCH v2 08/16] ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()

2018-01-10 Thread Nicolin Chen
This patch cleans fsl_ssi_setup_regvals() by following changes:
1) Moving DBG bits to the first lines.
2) Setting SSIE, RE/TE as default and cleaning it for AC97

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b449b8b..4399a22 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -575,18 +575,16 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
 {
struct fsl_ssi_regvals *vals = ssi->regvals;
 
-   vals[RX].sier = SSI_SIER_RFF0_EN;
+   vals[RX].sier = SSI_SIER_RFF0_EN | FSLSSI_SIER_DBG_RX_FLAGS;
vals[RX].srcr = SSI_SRCR_RFEN0;
-   vals[RX].scr = 0;
-   vals[TX].sier = SSI_SIER_TFE0_EN;
+   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
+   vals[TX].sier = SSI_SIER_TFE0_EN | FSLSSI_SIER_DBG_TX_FLAGS;
vals[TX].stcr = SSI_STCR_TFEN0;
-   vals[TX].scr = 0;
+   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
 
/* AC97 has already enabled SSIEN, RE and TE, so ignore them */
-   if (!fsl_ssi_is_ac97(ssi)) {
-   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
-   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
-   }
+   if (fsl_ssi_is_ac97(ssi))
+   vals[RX].scr = vals[TX].scr = 0;
 
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
@@ -595,9 +593,6 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
vals[RX].sier |= SSI_SIER_RIE;
vals[TX].sier |= SSI_SIER_TIE;
}
-
-   vals[RX].sier |= FSLSSI_SIER_DBG_RX_FLAGS;
-   vals[TX].sier |= FSLSSI_SIER_DBG_TX_FLAGS;
 }
 
 static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi)
-- 
2.7.4



[PATCH v2 07/16] ASoC: fsl_ssi: Add DAIFMT define for AC97

2018-01-10 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() bypasses an undefined format for AC97
mode. However, it's not really necessary if AC97 has its complete
format defined.

So this patch adds a DAIFMT macro of complete format including a
clock direction and polarity.

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 09a571a..b449b8b 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -86,6 +86,16 @@
 SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
+/*
+ * In AC97 mode, TXDIR bit is forced to 0 and TFDIR bit is forced to 1:
+ *  - SSI inputs external bit clock and outputs frame sync clock -- CBM_CFS
+ *  - Also have NB_NF to mark these two clocks will not be inverted
+ */
+#define FSLSSI_AC97_DAIFMT \
+   (SND_SOC_DAIFMT_AC97 | \
+SND_SOC_DAIFMT_CBM_CFS | \
+SND_SOC_DAIFMT_NB_NF)
+
 #define FSLSSI_SIER_DBG_RX_FLAGS \
(SSI_SIER_RFF0_EN | \
 SSI_SIER_RLS_EN | \
@@ -959,8 +969,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
scr &= ~SSI_SCR_SYS_CLK_EN;
break;
default:
-   if (!fsl_ssi_is_ac97(ssi))
-   return -EINVAL;
+   return -EINVAL;
}
 
stcr |= strcr;
@@ -1367,7 +1376,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = SND_SOC_DAIFMT_AC97;
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
}
 
/* Select DMA or FIQ */
-- 
2.7.4



[PATCH v2 08/16] ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()

2018-01-10 Thread Nicolin Chen
This patch cleans fsl_ssi_setup_regvals() by following changes:
1) Moving DBG bits to the first lines.
2) Setting SSIE, RE/TE as default and cleaning it for AC97

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b449b8b..4399a22 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -575,18 +575,16 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
 {
struct fsl_ssi_regvals *vals = ssi->regvals;
 
-   vals[RX].sier = SSI_SIER_RFF0_EN;
+   vals[RX].sier = SSI_SIER_RFF0_EN | FSLSSI_SIER_DBG_RX_FLAGS;
vals[RX].srcr = SSI_SRCR_RFEN0;
-   vals[RX].scr = 0;
-   vals[TX].sier = SSI_SIER_TFE0_EN;
+   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
+   vals[TX].sier = SSI_SIER_TFE0_EN | FSLSSI_SIER_DBG_TX_FLAGS;
vals[TX].stcr = SSI_STCR_TFEN0;
-   vals[TX].scr = 0;
+   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
 
/* AC97 has already enabled SSIEN, RE and TE, so ignore them */
-   if (!fsl_ssi_is_ac97(ssi)) {
-   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
-   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
-   }
+   if (fsl_ssi_is_ac97(ssi))
+   vals[RX].scr = vals[TX].scr = 0;
 
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
@@ -595,9 +593,6 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
vals[RX].sier |= SSI_SIER_RIE;
vals[TX].sier |= SSI_SIER_TIE;
}
-
-   vals[RX].sier |= FSLSSI_SIER_DBG_RX_FLAGS;
-   vals[TX].sier |= FSLSSI_SIER_DBG_TX_FLAGS;
 }
 
 static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi)
-- 
2.7.4



[PATCH v2 07/16] ASoC: fsl_ssi: Add DAIFMT define for AC97

2018-01-10 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() bypasses an undefined format for AC97
mode. However, it's not really necessary if AC97 has its complete
format defined.

So this patch adds a DAIFMT macro of complete format including a
clock direction and polarity.

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 09a571a..b449b8b 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -86,6 +86,16 @@
 SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
+/*
+ * In AC97 mode, TXDIR bit is forced to 0 and TFDIR bit is forced to 1:
+ *  - SSI inputs external bit clock and outputs frame sync clock -- CBM_CFS
+ *  - Also have NB_NF to mark these two clocks will not be inverted
+ */
+#define FSLSSI_AC97_DAIFMT \
+   (SND_SOC_DAIFMT_AC97 | \
+SND_SOC_DAIFMT_CBM_CFS | \
+SND_SOC_DAIFMT_NB_NF)
+
 #define FSLSSI_SIER_DBG_RX_FLAGS \
(SSI_SIER_RFF0_EN | \
 SSI_SIER_RLS_EN | \
@@ -959,8 +969,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
scr &= ~SSI_SCR_SYS_CLK_EN;
break;
default:
-   if (!fsl_ssi_is_ac97(ssi))
-   return -EINVAL;
+   return -EINVAL;
}
 
stcr |= strcr;
@@ -1367,7 +1376,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = SND_SOC_DAIFMT_AC97;
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
}
 
/* Select DMA or FIQ */
-- 
2.7.4



[PATCH v2 10/16] ASoC: fsl_ssi: Use snd_soc_init_dma_data instead

2018-01-10 Thread Nicolin Chen
Since there is a helper function, use it to help readability.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e75b57d..2c179a7 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1105,10 +1105,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
-   if (ssi->soc->imx && ssi->use_dma) {
-   dai->playback_dma_data = >dma_params_tx;
-   dai->capture_dma_data = >dma_params_rx;
-   }
+   if (ssi->soc->imx && ssi->use_dma)
+   snd_soc_dai_init_dma_data(dai, >dma_params_tx,
+ >dma_params_rx);
 
return 0;
 }
-- 
2.7.4



[PATCH v2 13/16] ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()

2018-01-10 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() is a helper function being called from
fsl_ssi_set_dai_fmt() as an ASoC operation and fsl_ssi_hw_init()
mainly for AC97 format initialization.

This patch cleans the _fsl_ssi_set_dai_fmt() in following ways:
* Removing *dev pointer in the parameters as it's included in the
  *ssi pointer of struct fsl_ssi.
* Using regmap_update_bits() instead of regmap_read() with masking
  the value manually.
* Removing TXBIT0 configurations since this bit is set to 1 as its
  reset value and there is no use case so far to unset it. And it
  is safe to remove since regmap_update_bits() won't touch it.
* Moving baudclk check to the switch-case routine to skip the I2S
  master check. And moving SxCCR.DC settings after baudclk check.
* Adding format settings for SND_SOC_DAIFMT_AC97 like others.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 70 ++---
 1 file changed, 31 insertions(+), 39 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 178c192..213962a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -855,42 +855,27 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream 
*substream,
return 0;
 }
 
-static int _fsl_ssi_set_dai_fmt(struct device *dev,
-   struct fsl_ssi *ssi, unsigned int fmt)
+static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
 {
-   struct regmap *regs = ssi->regs;
-   u32 strcr = 0, stcr, srcr, scr, mask;
+   u32 strcr = 0, scr = 0, stcr, srcr, mask;
 
ssi->dai_fmt = fmt;
 
-   if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "missing baudclk for master mode\n");
-   return -EINVAL;
-   }
-
-   regmap_read(regs, REG_SSI_SCR, );
-   scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
scr |= SSI_SCR_SYNC_TX_FS;
 
-   mask = SSI_STCR_TXBIT0 | SSI_STCR_TFDIR | SSI_STCR_TXDIR |
-  SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TFSL | SSI_STCR_TEFS;
-   regmap_read(regs, REG_SSI_STCR, );
-   regmap_read(regs, REG_SSI_SRCR, );
-   stcr &= ~mask;
-   srcr &= ~mask;
-
/* Use Network mode as default */
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,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
-   regmap_update_bits(regs, REG_SSI_SRCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
+   if (IS_ERR(ssi->baudclk)) {
+   dev_err(ssi->dev,
+   "missing baudclk for master mode\n");
+   return -EINVAL;
+   }
ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -900,30 +885,34 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
+   regmap_update_bits(ssi->regs, REG_SSI_STCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+   regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+
/* Data on rising edge of bclk, frame low, 1clk before data */
-   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_LEFT_J:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP;
+   strcr |= SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_DSP_A:
/* Data on rising edge of bclk, frame high, 1clk before data */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_DSP_B:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TXBIT0;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of bclk, frame high, 1clk before data */
-   ssi->i2s_net |= SSI_SCR_I2S_MODE_NORMAL;
+   strcr |= 

[PATCH v2 10/16] ASoC: fsl_ssi: Use snd_soc_init_dma_data instead

2018-01-10 Thread Nicolin Chen
Since there is a helper function, use it to help readability.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e75b57d..2c179a7 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1105,10 +1105,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
-   if (ssi->soc->imx && ssi->use_dma) {
-   dai->playback_dma_data = >dma_params_tx;
-   dai->capture_dma_data = >dma_params_rx;
-   }
+   if (ssi->soc->imx && ssi->use_dma)
+   snd_soc_dai_init_dma_data(dai, >dma_params_tx,
+ >dma_params_rx);
 
return 0;
 }
-- 
2.7.4



[PATCH v2 13/16] ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()

2018-01-10 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() is a helper function being called from
fsl_ssi_set_dai_fmt() as an ASoC operation and fsl_ssi_hw_init()
mainly for AC97 format initialization.

This patch cleans the _fsl_ssi_set_dai_fmt() in following ways:
* Removing *dev pointer in the parameters as it's included in the
  *ssi pointer of struct fsl_ssi.
* Using regmap_update_bits() instead of regmap_read() with masking
  the value manually.
* Removing TXBIT0 configurations since this bit is set to 1 as its
  reset value and there is no use case so far to unset it. And it
  is safe to remove since regmap_update_bits() won't touch it.
* Moving baudclk check to the switch-case routine to skip the I2S
  master check. And moving SxCCR.DC settings after baudclk check.
* Adding format settings for SND_SOC_DAIFMT_AC97 like others.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 70 ++---
 1 file changed, 31 insertions(+), 39 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 178c192..213962a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -855,42 +855,27 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream 
*substream,
return 0;
 }
 
-static int _fsl_ssi_set_dai_fmt(struct device *dev,
-   struct fsl_ssi *ssi, unsigned int fmt)
+static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
 {
-   struct regmap *regs = ssi->regs;
-   u32 strcr = 0, stcr, srcr, scr, mask;
+   u32 strcr = 0, scr = 0, stcr, srcr, mask;
 
ssi->dai_fmt = fmt;
 
-   if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "missing baudclk for master mode\n");
-   return -EINVAL;
-   }
-
-   regmap_read(regs, REG_SSI_SCR, );
-   scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
scr |= SSI_SCR_SYNC_TX_FS;
 
-   mask = SSI_STCR_TXBIT0 | SSI_STCR_TFDIR | SSI_STCR_TXDIR |
-  SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TFSL | SSI_STCR_TEFS;
-   regmap_read(regs, REG_SSI_STCR, );
-   regmap_read(regs, REG_SSI_SRCR, );
-   stcr &= ~mask;
-   srcr &= ~mask;
-
/* Use Network mode as default */
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,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
-   regmap_update_bits(regs, REG_SSI_SRCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
+   if (IS_ERR(ssi->baudclk)) {
+   dev_err(ssi->dev,
+   "missing baudclk for master mode\n");
+   return -EINVAL;
+   }
ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -900,30 +885,34 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
+   regmap_update_bits(ssi->regs, REG_SSI_STCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+   regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+
/* Data on rising edge of bclk, frame low, 1clk before data */
-   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_LEFT_J:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP;
+   strcr |= SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_DSP_A:
/* Data on rising edge of bclk, frame high, 1clk before data */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_DSP_B:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TXBIT0;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of bclk, frame high, 1clk before data */
-   ssi->i2s_net |= SSI_SCR_I2S_MODE_NORMAL;
+   strcr |= SSI_STCR_TEFS;
break;

[PATCH v2 06/16] ASoC: fsl_ssi: Clean up helper functions of trigger()

2018-01-10 Thread Nicolin Chen
The trigger() calls fsl_ssi_tx_config() and fsl_ssi_rx_config(),
and both of them jump to fsl_ssi_config(). And fsl_ssi_config()
later calls another fsl_ssi_rxtx_config().

However, the whole routine, especially fsl_ssi_config() function,
is too complicated because of the folowing reasons:
1) It has to handle the concern of the opposite stream.
2) It has to handle cases of offline configurations support.
3) It has to handle enable and disable operations while they're
   mostly different.

Since the enable and disable routines have more differences than
TX and RX rountines, this patch simplifies these helper functions
with the following changes:
- Changing to two helper functions of enable and disable instead
  of TX and RX.
- Removing fsl_ssi_rxtx_config() by separately integrating it to
  two newly introduced enable & disable functions.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 256 +++-
 1 file changed, 122 insertions(+), 134 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 263c067..09a571a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -378,31 +378,83 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 }
 
 /**
- * Enable or disable all rx/tx config flags at once
+ * Set SCR, SIER, STCR and SRCR registers with cached values in regvals
+ *
+ * Notes:
+ * 1) For offline_config SoCs, enable all necessary bits of both streams
+ *when 1st stream starts, even if the opposite stream will not start
+ * 2) It also clears FIFO before setting regvals; SOR is safe to set online
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
+static void fsl_ssi_config_enable(struct fsl_ssi *ssi, bool tx)
 {
-   struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *vals = ssi->regvals;
+   bool dir = tx ? TX : RX;
+   u32 sier, srcr, stcr;
 
-   if (enable) {
-   regmap_update_bits(regs, REG_SSI_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);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr,
-  vals[RX].stcr | vals[TX].stcr);
+   /* Clear dirty data in the FIFO; It also prevents channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
+
+   /*
+* On offline_config SoCs, SxCR and SIER are already configured when
+* the previous stream started. So skip all SxCR and SIER settings
+* to prevent online reconfigurations, then jump to set SCR directly
+*/
+   if (ssi->soc->offline_config && ssi->streams)
+   goto enable_scr;
+
+   if (ssi->soc->offline_config) {
+   /*
+* Online reconfiguration not supported, so enable all bits for
+* both streams at once to avoid necessity of reconfigurations
+*/
+   srcr = vals[RX].srcr | vals[TX].srcr;
+   stcr = vals[RX].stcr | vals[TX].stcr;
+   sier = vals[RX].sier | vals[TX].sier;
} else {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr, 0);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr, 0);
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier, 0);
+   /* Otherwise, only set bits for the current stream */
+   srcr = vals[dir].srcr;
+   stcr = vals[dir].stcr;
+   sier = vals[dir].sier;
}
+
+   /* Configure SRCR, STCR and SIER at once */
+   regmap_update_bits(ssi->regs, REG_SSI_SRCR, srcr, srcr);
+   regmap_update_bits(ssi->regs, REG_SSI_STCR, stcr, stcr);
+   regmap_update_bits(ssi->regs, REG_SSI_SIER, sier, sier);
+
+enable_scr:
+   /*
+* Start DMA before setting TE to avoid FIFO underrun
+* which may cause a channel slip or a channel swap
+*
+* TODO: FIQ cases might also need this upon testing
+*/
+   if (ssi->use_dma && tx) {
+   int try = 100;
+   u32 sfcsr;
+
+   /* Enable SSI first to send TX DMA request */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_SSIEN, SSI_SCR_SSIEN);
+
+   /* Busy wait until TX FIFO not empty -- DMA working */
+   do {
+   

[PATCH v2 06/16] ASoC: fsl_ssi: Clean up helper functions of trigger()

2018-01-10 Thread Nicolin Chen
The trigger() calls fsl_ssi_tx_config() and fsl_ssi_rx_config(),
and both of them jump to fsl_ssi_config(). And fsl_ssi_config()
later calls another fsl_ssi_rxtx_config().

However, the whole routine, especially fsl_ssi_config() function,
is too complicated because of the folowing reasons:
1) It has to handle the concern of the opposite stream.
2) It has to handle cases of offline configurations support.
3) It has to handle enable and disable operations while they're
   mostly different.

Since the enable and disable routines have more differences than
TX and RX rountines, this patch simplifies these helper functions
with the following changes:
- Changing to two helper functions of enable and disable instead
  of TX and RX.
- Removing fsl_ssi_rxtx_config() by separately integrating it to
  two newly introduced enable & disable functions.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 256 +++-
 1 file changed, 122 insertions(+), 134 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 263c067..09a571a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -378,31 +378,83 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 }
 
 /**
- * Enable or disable all rx/tx config flags at once
+ * Set SCR, SIER, STCR and SRCR registers with cached values in regvals
+ *
+ * Notes:
+ * 1) For offline_config SoCs, enable all necessary bits of both streams
+ *when 1st stream starts, even if the opposite stream will not start
+ * 2) It also clears FIFO before setting regvals; SOR is safe to set online
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
+static void fsl_ssi_config_enable(struct fsl_ssi *ssi, bool tx)
 {
-   struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *vals = ssi->regvals;
+   bool dir = tx ? TX : RX;
+   u32 sier, srcr, stcr;
 
-   if (enable) {
-   regmap_update_bits(regs, REG_SSI_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);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr,
-  vals[RX].stcr | vals[TX].stcr);
+   /* Clear dirty data in the FIFO; It also prevents channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
+
+   /*
+* On offline_config SoCs, SxCR and SIER are already configured when
+* the previous stream started. So skip all SxCR and SIER settings
+* to prevent online reconfigurations, then jump to set SCR directly
+*/
+   if (ssi->soc->offline_config && ssi->streams)
+   goto enable_scr;
+
+   if (ssi->soc->offline_config) {
+   /*
+* Online reconfiguration not supported, so enable all bits for
+* both streams at once to avoid necessity of reconfigurations
+*/
+   srcr = vals[RX].srcr | vals[TX].srcr;
+   stcr = vals[RX].stcr | vals[TX].stcr;
+   sier = vals[RX].sier | vals[TX].sier;
} else {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr, 0);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr, 0);
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier, 0);
+   /* Otherwise, only set bits for the current stream */
+   srcr = vals[dir].srcr;
+   stcr = vals[dir].stcr;
+   sier = vals[dir].sier;
}
+
+   /* Configure SRCR, STCR and SIER at once */
+   regmap_update_bits(ssi->regs, REG_SSI_SRCR, srcr, srcr);
+   regmap_update_bits(ssi->regs, REG_SSI_STCR, stcr, stcr);
+   regmap_update_bits(ssi->regs, REG_SSI_SIER, sier, sier);
+
+enable_scr:
+   /*
+* Start DMA before setting TE to avoid FIFO underrun
+* which may cause a channel slip or a channel swap
+*
+* TODO: FIQ cases might also need this upon testing
+*/
+   if (ssi->use_dma && tx) {
+   int try = 100;
+   u32 sfcsr;
+
+   /* Enable SSI first to send TX DMA request */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_SSIEN, SSI_SCR_SSIEN);
+
+   /* Busy wait until TX FIFO not empty -- DMA working */
+   do {
+   regmap_read(ssi->regs, REG_SSI_SFCSR, );
+

[PATCH v2 12/16] ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()

2018-01-10 Thread Nicolin Chen
AC97 configures most of registers earlier to start a communication
with CODECs in order to successfully initialize CODEC. Currently,
_fsl_ssi_set_dai_fmt() and fsl_ssi_setup_ac97() are called to get
all SSI registers properly set.

Since now the driver has a fsl_ssi_hw_init() to handle all register
initial settings, this patch moves those register settings of AC97
to the fsl_ssi_hw_init() as well.

Meanwhile it applies _fsl_ssi_set_dai_fmt() call to AC97 only since
other formats would be configured via normal set_dai_fmt() directly.

This patch also adds fsl_ssi_hw_clean() to cleanup control bits for
AC97 in the platform remote() function.

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 36e370e..178c192 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -982,9 +982,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
-   fsl_ssi_setup_ac97(ssi);
-
return 0;
 }
 
@@ -1250,10 +1247,28 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
regmap_update_bits(ssi->regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
 
+   /* AC97 should start earlier to communicate with CODECs */
+   if (fsl_ssi_is_ac97(ssi)) {
+   _fsl_ssi_set_dai_fmt(ssi->dev, ssi, ssi->dai_fmt);
+   fsl_ssi_setup_ac97(ssi);
+   }
+
return 0;
 }
 
 /**
+ * Clear SSI registers
+ */
+static void fsl_ssi_hw_clean(struct fsl_ssi *ssi)
+{
+   /* Disable registers for AC97 */
+   if (fsl_ssi_is_ac97(ssi)) {
+   regmap_write(ssi->regs, REG_SSI_SCR, 0);
+   regmap_write(ssi->regs, REG_SSI_SACNT, 0);
+   regmap_write(ssi->regs, REG_SSI_SOR, 0);
+   }
+}
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1535,9 +1550,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
}
 
 done:
-   if (ssi->dai_fmt)
-   _fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
-
/* Initially configures SSI registers */
fsl_ssi_hw_init(ssi);
 
@@ -1582,6 +1594,8 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 {
struct fsl_ssi *ssi = dev_get_drvdata(>dev);
 
+   fsl_ssi_hw_clean(ssi);
+
fsl_ssi_debugfs_remove(>dbg_stats);
 
if (ssi->pdev)
-- 
2.7.4



[PATCH v2 14/16] ASoC: fsl_ssi: Remove cpu_dai_drv from fsl_ssi structure

2018-01-10 Thread Nicolin Chen
The cpu_dai_drv is only used for symmetric_rates. So this patch replaces
it with a synchronous boolean flag.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 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 213962a..716603c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -208,11 +208,11 @@ struct fsl_ssi_soc_data {
  *
  * @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
  * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
+ * @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK
  * @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
@@ -253,11 +253,11 @@ struct fsl_ssi_soc_data {
 struct fsl_ssi {
struct regmap *regs;
int irq;
-   struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
u8 streams;
u8 i2s_net;
+   bool synchronous;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -668,7 +668,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
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;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
unsigned int slots = params_channels(hw_params);
@@ -676,6 +675,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
u64 sub, savesub = 10;
unsigned int freq;
bool baudclk_is_used;
+   int ret;
 
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
@@ -754,7 +754,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
/* STCCR is used for RX in synchronous mode */
-   tx2 = tx || synchronous;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
@@ -802,7 +802,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->cpu_dai_drv.symmetric_rates)
+   if (enabled && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
@@ -834,7 +834,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
@@ -959,7 +959,7 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, 
unsigned int fmt)
srcr = strcr;
 
/* Set SYN mode and clear RXDIR bit when using SYN or AC97 mode */
-   if (ssi->cpu_dai_drv.symmetric_rates || fsl_ssi_is_ac97(ssi)) {
+   if (ssi->synchronous || fsl_ssi_is_ac97(ssi)) {
srcr &= ~SSI_SRCR_RXDIR;
scr |= SSI_SCR_SYN;
}
@@ -1360,6 +1360,7 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
 
 static int fsl_ssi_probe(struct platform_device *pdev)
 {
+   struct snd_soc_dai_driver *cpu_dai_drv;
struct fsl_ssi *ssi;
int ret = 0;
struct device_node *np = pdev->dev.of_node;
@@ -1394,14 +1395,12 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ssi->use_dma = !of_property_read_bool(np, "fsl,fiq-stream-filter");
 
if (fsl_ssi_is_ac97(ssi)) {
-   memcpy(>cpu_dai_drv, _ssi_ac97_dai,
-  sizeof(fsl_ssi_ac97_dai));
+   cpu_dai_drv = _ssi_ac97_dai;
fsl_ac97_data = ssi;
} else {
-   memcpy(>cpu_dai_drv, _ssi_dai_template,
-  sizeof(fsl_ssi_dai_template));
+   cpu_dai_drv = _ssi_dai_template;
}
-   ssi->cpu_dai_drv.name = dev_name(dev);
+   cpu_dai_drv->name = dev_name(dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iomem = devm_ioremap_resource(dev, res);
@@ -1439,11 +1438,12 @@ static int fsl_ssi_probe(struct platform_device *pdev)
/* Set software limitations for synchronous mode */
if 

[PATCH v2 12/16] ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()

2018-01-10 Thread Nicolin Chen
AC97 configures most of registers earlier to start a communication
with CODECs in order to successfully initialize CODEC. Currently,
_fsl_ssi_set_dai_fmt() and fsl_ssi_setup_ac97() are called to get
all SSI registers properly set.

Since now the driver has a fsl_ssi_hw_init() to handle all register
initial settings, this patch moves those register settings of AC97
to the fsl_ssi_hw_init() as well.

Meanwhile it applies _fsl_ssi_set_dai_fmt() call to AC97 only since
other formats would be configured via normal set_dai_fmt() directly.

This patch also adds fsl_ssi_hw_clean() to cleanup control bits for
AC97 in the platform remote() function.

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

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 36e370e..178c192 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -982,9 +982,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
-   fsl_ssi_setup_ac97(ssi);
-
return 0;
 }
 
@@ -1250,10 +1247,28 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
regmap_update_bits(ssi->regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
 
+   /* AC97 should start earlier to communicate with CODECs */
+   if (fsl_ssi_is_ac97(ssi)) {
+   _fsl_ssi_set_dai_fmt(ssi->dev, ssi, ssi->dai_fmt);
+   fsl_ssi_setup_ac97(ssi);
+   }
+
return 0;
 }
 
 /**
+ * Clear SSI registers
+ */
+static void fsl_ssi_hw_clean(struct fsl_ssi *ssi)
+{
+   /* Disable registers for AC97 */
+   if (fsl_ssi_is_ac97(ssi)) {
+   regmap_write(ssi->regs, REG_SSI_SCR, 0);
+   regmap_write(ssi->regs, REG_SSI_SACNT, 0);
+   regmap_write(ssi->regs, REG_SSI_SOR, 0);
+   }
+}
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1535,9 +1550,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
}
 
 done:
-   if (ssi->dai_fmt)
-   _fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
-
/* Initially configures SSI registers */
fsl_ssi_hw_init(ssi);
 
@@ -1582,6 +1594,8 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 {
struct fsl_ssi *ssi = dev_get_drvdata(>dev);
 
+   fsl_ssi_hw_clean(ssi);
+
fsl_ssi_debugfs_remove(>dbg_stats);
 
if (ssi->pdev)
-- 
2.7.4



[PATCH v2 14/16] ASoC: fsl_ssi: Remove cpu_dai_drv from fsl_ssi structure

2018-01-10 Thread Nicolin Chen
The cpu_dai_drv is only used for symmetric_rates. So this patch replaces
it with a synchronous boolean flag.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 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 213962a..716603c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -208,11 +208,11 @@ struct fsl_ssi_soc_data {
  *
  * @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
  * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
+ * @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK
  * @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
@@ -253,11 +253,11 @@ struct fsl_ssi_soc_data {
 struct fsl_ssi {
struct regmap *regs;
int irq;
-   struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
u8 streams;
u8 i2s_net;
+   bool synchronous;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -668,7 +668,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
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;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
unsigned int slots = params_channels(hw_params);
@@ -676,6 +675,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
u64 sub, savesub = 10;
unsigned int freq;
bool baudclk_is_used;
+   int ret;
 
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
@@ -754,7 +754,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
/* STCCR is used for RX in synchronous mode */
-   tx2 = tx || synchronous;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
@@ -802,7 +802,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->cpu_dai_drv.symmetric_rates)
+   if (enabled && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
@@ -834,7 +834,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
@@ -959,7 +959,7 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, 
unsigned int fmt)
srcr = strcr;
 
/* Set SYN mode and clear RXDIR bit when using SYN or AC97 mode */
-   if (ssi->cpu_dai_drv.symmetric_rates || fsl_ssi_is_ac97(ssi)) {
+   if (ssi->synchronous || fsl_ssi_is_ac97(ssi)) {
srcr &= ~SSI_SRCR_RXDIR;
scr |= SSI_SCR_SYN;
}
@@ -1360,6 +1360,7 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
 
 static int fsl_ssi_probe(struct platform_device *pdev)
 {
+   struct snd_soc_dai_driver *cpu_dai_drv;
struct fsl_ssi *ssi;
int ret = 0;
struct device_node *np = pdev->dev.of_node;
@@ -1394,14 +1395,12 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ssi->use_dma = !of_property_read_bool(np, "fsl,fiq-stream-filter");
 
if (fsl_ssi_is_ac97(ssi)) {
-   memcpy(>cpu_dai_drv, _ssi_ac97_dai,
-  sizeof(fsl_ssi_ac97_dai));
+   cpu_dai_drv = _ssi_ac97_dai;
fsl_ac97_data = ssi;
} else {
-   memcpy(>cpu_dai_drv, _ssi_dai_template,
-  sizeof(fsl_ssi_dai_template));
+   cpu_dai_drv = _ssi_dai_template;
}
-   ssi->cpu_dai_drv.name = dev_name(dev);
+   cpu_dai_drv->name = dev_name(dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iomem = devm_ioremap_resource(dev, res);
@@ -1439,11 +1438,12 @@ static int fsl_ssi_probe(struct platform_device *pdev)
/* Set software limitations for synchronous mode */
if (!of_find_property(np, 

[PATCH v2 16/16] ASoC: fsl_ssi: Use ssi->streams instead of reading register

2018-01-10 Thread Nicolin Chen
Since ssi->streams is being updated along with SCR register and
its SSIEN bit, it's simpler to use it instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 0754eeb..52ddce1 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -796,11 +796,6 @@ 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;
-   int enabled;
-
-   regmap_read(regs, REG_SSI_SCR, );
-   enabled = scr & SSI_SCR_SSIEN;
 
/*
 * SSI is properly configured if it is enabled and running in
@@ -808,7 +803,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->synchronous)
+   if (ssi->streams && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-- 
2.7.4



[PATCH v2 15/16] ASoC: fsl_ssi: Move DT related code to a separate probe()

2018-01-10 Thread Nicolin Chen
This patch cleans up probe() function by moving all Device Tree
related code into a separate function. It allows the probe() to
be Device Tree independent. This will be very useful for future
integration of imx-ssi driver which has similar functionalities
while exists only because it supports non-DT cases.

This patch also moves symmetric_channels of AC97 from the probe
to the structure snd_soc_dai_driver for simplification.

Additionally, since PowerPC and AC97 use the same pdev pointer
to register a platform device, this patch also unifies related
code.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 204 +---
 1 file changed, 108 insertions(+), 96 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 716603c..0754eeb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -234,8 +234,12 @@ struct fsl_ssi_soc_data {
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
- *TODO: Should be replaced with simple-sound-card
+ * @card_pdev: Platform_device pointer when using fsl-ssi as sound card
+ * (PowerPC or AC97 only)
+ * @card_name: Platform_device name when using fsl-ssi as sound card
+ * (PowerPC or AC97 only)
+ * @card_idx: The index of SSI when registering a sound card
+ * (PowerPC or AC97 only)
  *
  * @dbg_stats: Debugging statistics
  *
@@ -279,7 +283,9 @@ struct fsl_ssi {
 
struct imx_pcm_fiq_params fiq_params;
 
-   struct platform_device *pdev;
+   struct platform_device *card_pdev;
+   char card_name[32];
+   u32 card_idx;
 
struct fsl_ssi_dbg dbg_stats;
 
@@ -1123,6 +1129,7 @@ static const struct snd_soc_component_driver 
fsl_ssi_component = {
 
 static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
.bus_control = true,
+   .symmetric_channels = 1,
.probe = fsl_ssi_dai_probe,
.playback = {
.stream_name = "AC97 Playback",
@@ -1274,9 +1281,7 @@ static void make_lowercase(char *s)
 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;
 
/* Backward compatible for a DT without ipg clock name assigned */
@@ -1310,14 +1315,8 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0;
 
-   /* Set to dual FIFO mode according to the SDMA sciprt */
-   ret = of_property_read_u32_array(np, "dmas", dmas, 4);
-   if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
-   ssi->use_dual_fifo = true;
-   /*
-* Use even numbers to avoid channel swap due to SDMA
-* script design
-*/
+   /* Use even numbers to avoid channel swap due to SDMA script design */
+   if (ssi->use_dual_fifo) {
ssi->dma_params_tx.maxburst &= ~0x1;
ssi->dma_params_rx.maxburst &= ~0x1;
}
@@ -1358,42 +1357,103 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
clk_disable_unprepare(ssi->clk);
 }
 
-static int fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
 {
-   struct snd_soc_dai_driver *cpu_dai_drv;
-   struct fsl_ssi *ssi;
-   int ret = 0;
-   struct device_node *np = pdev->dev.of_node;
-   struct device *dev = >dev;
+   struct device *dev = ssi->dev;
+   struct device_node *np = dev->of_node;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
-   struct resource *res;
-   void __iomem *iomem;
-   char name[64];
-   struct regmap_config regconfig = fsl_ssi_regconfig;
+   u32 dmas[4];
+   int ret;
 
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);
-   if (!ssi)
-   return -ENOMEM;
-
ssi->soc = of_id->data;
-   ssi->dev = dev;
+
+   ret = of_property_match_string(np, "clock-names", "ipg");
+   /* Get error code if not found */
+   ssi->has_ipg_clk_name = ret >= 0;
 
/* Check if being used in AC97 mode */
sprop = of_get_property(np, "fsl,mode", NULL);
-   if (sprop) {
-   if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
+   if (sprop && !strcmp(sprop, "ac97-slave")) {
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
+
+   ret = 

[PATCH v2 16/16] ASoC: fsl_ssi: Use ssi->streams instead of reading register

2018-01-10 Thread Nicolin Chen
Since ssi->streams is being updated along with SCR register and
its SSIEN bit, it's simpler to use it instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 0754eeb..52ddce1 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -796,11 +796,6 @@ 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;
-   int enabled;
-
-   regmap_read(regs, REG_SSI_SCR, );
-   enabled = scr & SSI_SCR_SSIEN;
 
/*
 * SSI is properly configured if it is enabled and running in
@@ -808,7 +803,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->synchronous)
+   if (ssi->streams && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-- 
2.7.4



[PATCH v2 15/16] ASoC: fsl_ssi: Move DT related code to a separate probe()

2018-01-10 Thread Nicolin Chen
This patch cleans up probe() function by moving all Device Tree
related code into a separate function. It allows the probe() to
be Device Tree independent. This will be very useful for future
integration of imx-ssi driver which has similar functionalities
while exists only because it supports non-DT cases.

This patch also moves symmetric_channels of AC97 from the probe
to the structure snd_soc_dai_driver for simplification.

Additionally, since PowerPC and AC97 use the same pdev pointer
to register a platform device, this patch also unifies related
code.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 204 +---
 1 file changed, 108 insertions(+), 96 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 716603c..0754eeb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -234,8 +234,12 @@ struct fsl_ssi_soc_data {
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
- *TODO: Should be replaced with simple-sound-card
+ * @card_pdev: Platform_device pointer when using fsl-ssi as sound card
+ * (PowerPC or AC97 only)
+ * @card_name: Platform_device name when using fsl-ssi as sound card
+ * (PowerPC or AC97 only)
+ * @card_idx: The index of SSI when registering a sound card
+ * (PowerPC or AC97 only)
  *
  * @dbg_stats: Debugging statistics
  *
@@ -279,7 +283,9 @@ struct fsl_ssi {
 
struct imx_pcm_fiq_params fiq_params;
 
-   struct platform_device *pdev;
+   struct platform_device *card_pdev;
+   char card_name[32];
+   u32 card_idx;
 
struct fsl_ssi_dbg dbg_stats;
 
@@ -1123,6 +1129,7 @@ static const struct snd_soc_component_driver 
fsl_ssi_component = {
 
 static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
.bus_control = true,
+   .symmetric_channels = 1,
.probe = fsl_ssi_dai_probe,
.playback = {
.stream_name = "AC97 Playback",
@@ -1274,9 +1281,7 @@ static void make_lowercase(char *s)
 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;
 
/* Backward compatible for a DT without ipg clock name assigned */
@@ -1310,14 +1315,8 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0;
 
-   /* Set to dual FIFO mode according to the SDMA sciprt */
-   ret = of_property_read_u32_array(np, "dmas", dmas, 4);
-   if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
-   ssi->use_dual_fifo = true;
-   /*
-* Use even numbers to avoid channel swap due to SDMA
-* script design
-*/
+   /* Use even numbers to avoid channel swap due to SDMA script design */
+   if (ssi->use_dual_fifo) {
ssi->dma_params_tx.maxburst &= ~0x1;
ssi->dma_params_rx.maxburst &= ~0x1;
}
@@ -1358,42 +1357,103 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
clk_disable_unprepare(ssi->clk);
 }
 
-static int fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
 {
-   struct snd_soc_dai_driver *cpu_dai_drv;
-   struct fsl_ssi *ssi;
-   int ret = 0;
-   struct device_node *np = pdev->dev.of_node;
-   struct device *dev = >dev;
+   struct device *dev = ssi->dev;
+   struct device_node *np = dev->of_node;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
-   struct resource *res;
-   void __iomem *iomem;
-   char name[64];
-   struct regmap_config regconfig = fsl_ssi_regconfig;
+   u32 dmas[4];
+   int ret;
 
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);
-   if (!ssi)
-   return -ENOMEM;
-
ssi->soc = of_id->data;
-   ssi->dev = dev;
+
+   ret = of_property_match_string(np, "clock-names", "ipg");
+   /* Get error code if not found */
+   ssi->has_ipg_clk_name = ret >= 0;
 
/* Check if being used in AC97 mode */
sprop = of_get_property(np, "fsl,mode", NULL);
-   if (sprop) {
-   if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
+   if (sprop && !strcmp(sprop, "ac97-slave")) {
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
+
+   ret = of_property_read_u32(np, "cell-index", >card_idx);
+   

[PATCH v2 11/16] ASoC: fsl_ssi: Move one-time configurations to probe()

2018-01-10 Thread Nicolin Chen
The probe() could handle some one-time configurations since
they will not be changed once being configured.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 39 ++-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 2c179a7..36e370e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -860,7 +860,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 {
struct regmap *regs = ssi->regs;
u32 strcr = 0, stcr, srcr, scr, mask;
-   u8 wm;
 
ssi->dai_fmt = fmt;
 
@@ -869,8 +868,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
-   fsl_ssi_setup_regvals(ssi);
-
regmap_read(regs, REG_SSI_SCR, );
scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
@@ -985,16 +982,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   wm = ssi->fifo_watermark;
-
-   regmap_write(regs, REG_SSI_SFCSR,
-SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
-SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
-
-   if (ssi->use_dual_fifo)
-   regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
 
@@ -1244,6 +1231,29 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
 };
 
 /**
+ * Initialize SSI registers
+ */
+static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
+{
+   u32 wm = ssi->fifo_watermark;
+
+   /* Initialize regvals */
+   fsl_ssi_setup_regvals(ssi);
+
+   /* Set watermarks */
+   regmap_write(ssi->regs, REG_SSI_SFCSR,
+SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
+SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
+
+   /* Enable Dual FIFO mode */
+   if (ssi->use_dual_fifo)
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
+
+   return 0;
+}
+
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1528,6 +1538,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (ssi->dai_fmt)
_fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
 
+   /* Initially configures SSI registers */
+   fsl_ssi_hw_init(ssi);
+
if (fsl_ssi_is_ac97(ssi)) {
u32 ssi_idx;
 
-- 
2.7.4



[PATCH v2 11/16] ASoC: fsl_ssi: Move one-time configurations to probe()

2018-01-10 Thread Nicolin Chen
The probe() could handle some one-time configurations since
they will not be changed once being configured.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 39 ++-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 2c179a7..36e370e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -860,7 +860,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 {
struct regmap *regs = ssi->regs;
u32 strcr = 0, stcr, srcr, scr, mask;
-   u8 wm;
 
ssi->dai_fmt = fmt;
 
@@ -869,8 +868,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
-   fsl_ssi_setup_regvals(ssi);
-
regmap_read(regs, REG_SSI_SCR, );
scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
@@ -985,16 +982,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   wm = ssi->fifo_watermark;
-
-   regmap_write(regs, REG_SSI_SFCSR,
-SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
-SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
-
-   if (ssi->use_dual_fifo)
-   regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
 
@@ -1244,6 +1231,29 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
 };
 
 /**
+ * Initialize SSI registers
+ */
+static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
+{
+   u32 wm = ssi->fifo_watermark;
+
+   /* Initialize regvals */
+   fsl_ssi_setup_regvals(ssi);
+
+   /* Set watermarks */
+   regmap_write(ssi->regs, REG_SSI_SFCSR,
+SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
+SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
+
+   /* Enable Dual FIFO mode */
+   if (ssi->use_dual_fifo)
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
+
+   return 0;
+}
+
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1528,6 +1538,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (ssi->dai_fmt)
_fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
 
+   /* Initially configures SSI registers */
+   fsl_ssi_hw_init(ssi);
+
if (fsl_ssi_is_ac97(ssi)) {
u32 ssi_idx;
 
-- 
2.7.4



[PATCH v2 02/16] ASoC: fsl_ssi: Clean up set_dai_tdm_slot()

2018-01-10 Thread Nicolin Chen
This patch replaces the register read with ssi->i2s_net for
simplification. It also removes masking SSIEN from scr value
since it's handled later by regmap_update_bits() to set this
scr value back.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c8bd353..491b660 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1051,9 +1051,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
}
 
/* The slot number should be >= 2 if using Network mode or I2S mode */
-   regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET;
-   if (val && slots < 2) {
+   if (ssi->i2s_net && slots < 2) {
dev_err(dai->dev, "slot number should be >= 2 in I2S or NET\n");
return -EINVAL;
}
@@ -1063,9 +1061,8 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
regmap_update_bits(regs, REG_SSI_SRCCR,
   SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
 
-   /* Save SSIEN bit of the SCR register */
+   /* Save the SCR register value */
regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_SSIEN;
/* Temporarily enable SSI to allow SxMSKs to be configurable */
regmap_update_bits(regs, REG_SSI_SCR, SSI_SCR_SSIEN, SSI_SCR_SSIEN);
 
-- 
2.7.4



[PATCH v2 02/16] ASoC: fsl_ssi: Clean up set_dai_tdm_slot()

2018-01-10 Thread Nicolin Chen
This patch replaces the register read with ssi->i2s_net for
simplification. It also removes masking SSIEN from scr value
since it's handled later by regmap_update_bits() to set this
scr value back.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c8bd353..491b660 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1051,9 +1051,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
}
 
/* The slot number should be >= 2 if using Network mode or I2S mode */
-   regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET;
-   if (val && slots < 2) {
+   if (ssi->i2s_net && slots < 2) {
dev_err(dai->dev, "slot number should be >= 2 in I2S or NET\n");
return -EINVAL;
}
@@ -1063,9 +1061,8 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
regmap_update_bits(regs, REG_SSI_SRCCR,
   SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
 
-   /* Save SSIEN bit of the SCR register */
+   /* Save the SCR register value */
regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_SSIEN;
/* Temporarily enable SSI to allow SxMSKs to be configurable */
regmap_update_bits(regs, REG_SSI_SCR, SSI_SCR_SSIEN, SSI_SCR_SSIEN);
 
-- 
2.7.4



Re: [RFC PATCH v2 6/6] x86/entry/pti: don't switch PGD on when pti_disable is set

2018-01-10 Thread Willy Tarreau
On Wed, Jan 10, 2018 at 11:50:46AM -0800, Linus Torvalds wrote:
> And the whole "NOW" vs "NEXT" is complete garbage. The obvious sane
> no-PTI interface is that it
> 
>  (a) inherits on fork/exec, so that you don't have to worry about how
> something is implemented (think "I want to run this kernel build
> without the PTI overhead", but also "I want to run this system daemon
> without PTI").
> 
>  (b) actual domain changes clear it (ie suid, whatever).
> 
> that make it useful for random uses of "I trust service XYZ".

OK. Do you want to see something *only* based on a wrapper (i.e. works
only after execve) or can we let the application apply the change to
itself ? I would also like to let applications re-enable the protection
for processes they're going to exec and not necessarily trust.

> So I'm NAK'ing this whole series on the grounds that it has several
> completely insane semantics and really need to be clarified, and where
> actual usage needs to be thought about a lot more.

In fact we were trying to limit the risk of propagating the protection
removal too far, and leave it only on the sensitive process which really
requires it. But your example of "running the kernel build without PTI"
makes sense from a user's perspective, and it completely contradicts
our initial assumptions.

After all I don't think the NOW vs NEXT is so fundamentally broken. We
could think about having one option for the current process only (which
is cleared by execve) so that applications can apply it to themselves
only without having to wonder about clearing it, and another one which
is only for wrappers and which passes execve(). For now I considered
that we could stop at the first execve, but if I just remove the
clearing of the NEXT flag, it matches your requirement for the kernel
build. After this it's just a matter of naming and placing them on the
mm rather than thread.

Willy


Re: [RFC PATCH v2 6/6] x86/entry/pti: don't switch PGD on when pti_disable is set

2018-01-10 Thread Willy Tarreau
On Wed, Jan 10, 2018 at 11:50:46AM -0800, Linus Torvalds wrote:
> And the whole "NOW" vs "NEXT" is complete garbage. The obvious sane
> no-PTI interface is that it
> 
>  (a) inherits on fork/exec, so that you don't have to worry about how
> something is implemented (think "I want to run this kernel build
> without the PTI overhead", but also "I want to run this system daemon
> without PTI").
> 
>  (b) actual domain changes clear it (ie suid, whatever).
> 
> that make it useful for random uses of "I trust service XYZ".

OK. Do you want to see something *only* based on a wrapper (i.e. works
only after execve) or can we let the application apply the change to
itself ? I would also like to let applications re-enable the protection
for processes they're going to exec and not necessarily trust.

> So I'm NAK'ing this whole series on the grounds that it has several
> completely insane semantics and really need to be clarified, and where
> actual usage needs to be thought about a lot more.

In fact we were trying to limit the risk of propagating the protection
removal too far, and leave it only on the sensitive process which really
requires it. But your example of "running the kernel build without PTI"
makes sense from a user's perspective, and it completely contradicts
our initial assumptions.

After all I don't think the NOW vs NEXT is so fundamentally broken. We
could think about having one option for the current process only (which
is cleared by execve) so that applications can apply it to themselves
only without having to wonder about clearing it, and another one which
is only for wrappers and which passes execve(). For now I considered
that we could stop at the first execve, but if I just remove the
clearing of the NEXT flag, it matches your requirement for the kernel
build. After this it's just a matter of naming and placing them on the
mm rather than thread.

Willy


[PATCH v3 RESEND] f2fs: support F2FS_IOC_PRECACHE_EXTENTS

2018-01-10 Thread Chao Yu
This patch introduces a new ioctl F2FS_IOC_PRECACHE_EXTENTS to precache
extent info like ext4, in order to gain better performance during
triggering AIO by eliminating synchronous waiting of mapping info.

Referred commit: 7869a4a6c5ca ("ext4: add support for extent pre-caching")

In addition, with newly added extent precache abilitiy, this patch add
to support FIEMAP_FLAG_CACHE in ->fiemap.

Signed-off-by: Chao Yu 
---
v3:
- rebase code.
 fs/f2fs/data.c | 39 +++
 fs/f2fs/f2fs.h |  4 
 fs/f2fs/file.c | 44 ++--
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 3c1a0f1a3e53..06a647a36356 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -861,6 +861,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct 
iov_iter *from)
map.m_len = 0;
 
map.m_next_pgofs = NULL;
+   map.m_next_extent = NULL;
map.m_seg_type = NO_CHECK_TYPE;
 
if (direct_io) {
@@ -927,6 +928,7 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
blkcnt_t prealloc;
struct extent_info ei = {0,0,0};
block_t blkaddr;
+   unsigned int start_pgofs;
 
if (!maxblocks)
return 0;
@@ -942,6 +944,8 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
map->m_pblk = ei.blk + pgofs - ei.fofs;
map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs);
map->m_flags = F2FS_MAP_MAPPED;
+   if (map->m_next_extent)
+   *map->m_next_extent = pgofs + map->m_len;
goto out;
}
 
@@ -960,10 +964,14 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
if (map->m_next_pgofs)
*map->m_next_pgofs =
get_next_page_offset(, pgofs);
+   if (map->m_next_extent)
+   *map->m_next_extent =
+   get_next_page_offset(, pgofs);
}
goto unlock_out;
}
 
+   start_pgofs = pgofs;
prealloc = 0;
last_ofs_in_node = ofs_in_node = dn.ofs_in_node;
end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
@@ -997,6 +1005,8 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
map->m_pblk = 0;
goto sync_out;
}
+   if (flag == F2FS_GET_BLOCK_PRECACHE)
+   goto sync_out;
if (flag == F2FS_GET_BLOCK_FIEMAP &&
blkaddr == NULL_ADDR) {
if (map->m_next_pgofs)
@@ -1055,6 +1065,16 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
else if (dn.ofs_in_node < end_offset)
goto next_block;
 
+   if (flag == F2FS_GET_BLOCK_PRECACHE) {
+   if (map->m_flags & F2FS_MAP_MAPPED) {
+   unsigned int ofs = start_pgofs - map->m_lblk;
+
+   f2fs_update_extent_cache_range(,
+   start_pgofs, map->m_pblk + ofs,
+   map->m_len - ofs);
+   }
+   }
+
f2fs_put_dnode();
 
if (create) {
@@ -1064,6 +1084,17 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
goto next_dnode;
 
 sync_out:
+   if (flag == F2FS_GET_BLOCK_PRECACHE) {
+   if (map->m_flags & F2FS_MAP_MAPPED) {
+   unsigned int ofs = start_pgofs - map->m_lblk;
+
+   f2fs_update_extent_cache_range(,
+   start_pgofs, map->m_pblk + ofs,
+   map->m_len - ofs);
+   }
+   if (map->m_next_extent)
+   *map->m_next_extent = pgofs + 1;
+   }
f2fs_put_dnode();
 unlock_out:
if (create) {
@@ -1085,6 +1116,7 @@ static int __get_data_block(struct inode *inode, sector_t 
iblock,
map.m_lblk = iblock;
map.m_len = bh->b_size >> inode->i_blkbits;
map.m_next_pgofs = next_pgofs;
+   map.m_next_extent = NULL;
map.m_seg_type = seg_type;
 
err = f2fs_map_blocks(inode, , create, flag);
@@ -1208,6 +1240,12 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
u32 flags = 0;
int ret = 0;
 
+   if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
+   ret = f2fs_precache_extents(inode);
+   if (ret)
+   return ret;
+   }
+
ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR);
if (ret)
return ret;
@@ -1309,6 +1347,7 @@ static int 

[PATCH v3 RESEND] f2fs: support F2FS_IOC_PRECACHE_EXTENTS

2018-01-10 Thread Chao Yu
This patch introduces a new ioctl F2FS_IOC_PRECACHE_EXTENTS to precache
extent info like ext4, in order to gain better performance during
triggering AIO by eliminating synchronous waiting of mapping info.

Referred commit: 7869a4a6c5ca ("ext4: add support for extent pre-caching")

In addition, with newly added extent precache abilitiy, this patch add
to support FIEMAP_FLAG_CACHE in ->fiemap.

Signed-off-by: Chao Yu 
---
v3:
- rebase code.
 fs/f2fs/data.c | 39 +++
 fs/f2fs/f2fs.h |  4 
 fs/f2fs/file.c | 44 ++--
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 3c1a0f1a3e53..06a647a36356 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -861,6 +861,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct 
iov_iter *from)
map.m_len = 0;
 
map.m_next_pgofs = NULL;
+   map.m_next_extent = NULL;
map.m_seg_type = NO_CHECK_TYPE;
 
if (direct_io) {
@@ -927,6 +928,7 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
blkcnt_t prealloc;
struct extent_info ei = {0,0,0};
block_t blkaddr;
+   unsigned int start_pgofs;
 
if (!maxblocks)
return 0;
@@ -942,6 +944,8 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
map->m_pblk = ei.blk + pgofs - ei.fofs;
map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs);
map->m_flags = F2FS_MAP_MAPPED;
+   if (map->m_next_extent)
+   *map->m_next_extent = pgofs + map->m_len;
goto out;
}
 
@@ -960,10 +964,14 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
if (map->m_next_pgofs)
*map->m_next_pgofs =
get_next_page_offset(, pgofs);
+   if (map->m_next_extent)
+   *map->m_next_extent =
+   get_next_page_offset(, pgofs);
}
goto unlock_out;
}
 
+   start_pgofs = pgofs;
prealloc = 0;
last_ofs_in_node = ofs_in_node = dn.ofs_in_node;
end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
@@ -997,6 +1005,8 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
map->m_pblk = 0;
goto sync_out;
}
+   if (flag == F2FS_GET_BLOCK_PRECACHE)
+   goto sync_out;
if (flag == F2FS_GET_BLOCK_FIEMAP &&
blkaddr == NULL_ADDR) {
if (map->m_next_pgofs)
@@ -1055,6 +1065,16 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
else if (dn.ofs_in_node < end_offset)
goto next_block;
 
+   if (flag == F2FS_GET_BLOCK_PRECACHE) {
+   if (map->m_flags & F2FS_MAP_MAPPED) {
+   unsigned int ofs = start_pgofs - map->m_lblk;
+
+   f2fs_update_extent_cache_range(,
+   start_pgofs, map->m_pblk + ofs,
+   map->m_len - ofs);
+   }
+   }
+
f2fs_put_dnode();
 
if (create) {
@@ -1064,6 +1084,17 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
goto next_dnode;
 
 sync_out:
+   if (flag == F2FS_GET_BLOCK_PRECACHE) {
+   if (map->m_flags & F2FS_MAP_MAPPED) {
+   unsigned int ofs = start_pgofs - map->m_lblk;
+
+   f2fs_update_extent_cache_range(,
+   start_pgofs, map->m_pblk + ofs,
+   map->m_len - ofs);
+   }
+   if (map->m_next_extent)
+   *map->m_next_extent = pgofs + 1;
+   }
f2fs_put_dnode();
 unlock_out:
if (create) {
@@ -1085,6 +1116,7 @@ static int __get_data_block(struct inode *inode, sector_t 
iblock,
map.m_lblk = iblock;
map.m_len = bh->b_size >> inode->i_blkbits;
map.m_next_pgofs = next_pgofs;
+   map.m_next_extent = NULL;
map.m_seg_type = seg_type;
 
err = f2fs_map_blocks(inode, , create, flag);
@@ -1208,6 +1240,12 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
u32 flags = 0;
int ret = 0;
 
+   if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
+   ret = f2fs_precache_extents(inode);
+   if (ret)
+   return ret;
+   }
+
ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR);
if (ret)
return ret;
@@ -1309,6 +1347,7 @@ static int 

[PATCH v3 RESEND] f2fs: support FIEMAP_FLAG_XATTR

2018-01-10 Thread Chao Yu
This patch enables ->fiemap to handle FIEMAP_FLAG_XATTR flag for xattr
mapping info lookup purpose.

It makes f2fs passing generic/425 test in fstest.

Signed-off-by: Chao Yu 
---
 fs/f2fs/data.c | 69 +-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 12155ee90468..3c1a0f1a3e53 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1136,6 +1136,68 @@ static inline loff_t blk_to_logical(struct inode *inode, 
sector_t blk)
return (blk << inode->i_blkbits);
 }
 
+static int f2fs_xattr_fiemap(struct inode *inode,
+   struct fiemap_extent_info *fieinfo)
+{
+   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+   struct page *page;
+   struct node_info ni;
+   __u64 phys = 0, len;
+   __u32 flags;
+   nid_t xnid = F2FS_I(inode)->i_xattr_nid;
+   int err = 0;
+
+   if (f2fs_has_inline_xattr(inode)) {
+   int offset;
+
+   page = f2fs_grab_cache_page(NODE_MAPPING(sbi),
+   inode->i_ino, false);
+   if (!page)
+   return -ENOMEM;
+
+   get_node_info(sbi, inode->i_ino, );
+
+   phys = (__u64)blk_to_logical(inode, ni.blk_addr);
+   offset = offsetof(struct f2fs_inode, i_addr) +
+   sizeof(__le32) * (DEF_ADDRS_PER_INODE -
+   F2FS_INLINE_XATTR_ADDRS(inode));
+
+   phys += offset;
+   len = inline_xattr_size(inode);
+
+   f2fs_put_page(page, 1);
+
+   flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED;
+
+   if (!xnid)
+   flags |= FIEMAP_EXTENT_LAST;
+
+   err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags);
+   if (err || err == 1)
+   return err;
+   }
+
+   if (xnid) {
+   page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false);
+   if (!page)
+   return -ENOMEM;
+
+   get_node_info(sbi, xnid, );
+
+   phys = (__u64)blk_to_logical(inode, ni.blk_addr);
+   len = inode->i_sb->s_blocksize;
+
+   f2fs_put_page(page, 1);
+
+   flags = FIEMAP_EXTENT_LAST;
+   }
+
+   if (phys)
+   err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags);
+
+   return (err < 0 ? err : 0);
+}
+
 int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
 {
@@ -1146,12 +1208,17 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
u32 flags = 0;
int ret = 0;
 
-   ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
+   ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR);
if (ret)
return ret;
 
inode_lock(inode);
 
+   if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
+   ret = f2fs_xattr_fiemap(inode, fieinfo);
+   goto out;
+   }
+
if (f2fs_has_inline_data(inode)) {
ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
if (ret != -EAGAIN)
-- 
2.15.0.55.gc2ece9dc4de6



[PATCH v3 RESEND] f2fs: support FIEMAP_FLAG_XATTR

2018-01-10 Thread Chao Yu
This patch enables ->fiemap to handle FIEMAP_FLAG_XATTR flag for xattr
mapping info lookup purpose.

It makes f2fs passing generic/425 test in fstest.

Signed-off-by: Chao Yu 
---
 fs/f2fs/data.c | 69 +-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 12155ee90468..3c1a0f1a3e53 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1136,6 +1136,68 @@ static inline loff_t blk_to_logical(struct inode *inode, 
sector_t blk)
return (blk << inode->i_blkbits);
 }
 
+static int f2fs_xattr_fiemap(struct inode *inode,
+   struct fiemap_extent_info *fieinfo)
+{
+   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+   struct page *page;
+   struct node_info ni;
+   __u64 phys = 0, len;
+   __u32 flags;
+   nid_t xnid = F2FS_I(inode)->i_xattr_nid;
+   int err = 0;
+
+   if (f2fs_has_inline_xattr(inode)) {
+   int offset;
+
+   page = f2fs_grab_cache_page(NODE_MAPPING(sbi),
+   inode->i_ino, false);
+   if (!page)
+   return -ENOMEM;
+
+   get_node_info(sbi, inode->i_ino, );
+
+   phys = (__u64)blk_to_logical(inode, ni.blk_addr);
+   offset = offsetof(struct f2fs_inode, i_addr) +
+   sizeof(__le32) * (DEF_ADDRS_PER_INODE -
+   F2FS_INLINE_XATTR_ADDRS(inode));
+
+   phys += offset;
+   len = inline_xattr_size(inode);
+
+   f2fs_put_page(page, 1);
+
+   flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED;
+
+   if (!xnid)
+   flags |= FIEMAP_EXTENT_LAST;
+
+   err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags);
+   if (err || err == 1)
+   return err;
+   }
+
+   if (xnid) {
+   page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false);
+   if (!page)
+   return -ENOMEM;
+
+   get_node_info(sbi, xnid, );
+
+   phys = (__u64)blk_to_logical(inode, ni.blk_addr);
+   len = inode->i_sb->s_blocksize;
+
+   f2fs_put_page(page, 1);
+
+   flags = FIEMAP_EXTENT_LAST;
+   }
+
+   if (phys)
+   err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags);
+
+   return (err < 0 ? err : 0);
+}
+
 int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
 {
@@ -1146,12 +1208,17 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
u32 flags = 0;
int ret = 0;
 
-   ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
+   ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR);
if (ret)
return ret;
 
inode_lock(inode);
 
+   if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
+   ret = f2fs_xattr_fiemap(inode, fieinfo);
+   goto out;
+   }
+
if (f2fs_has_inline_data(inode)) {
ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
if (ret != -EAGAIN)
-- 
2.15.0.55.gc2ece9dc4de6



[PATCH v2] f2fs: fix to cover f2fs_inline_data_fiemap with inode_lock

2018-01-10 Thread Chao Yu
This patch fix to cover f2fs_inline_data_fiemap with inode_lock in order
to make that interface avoiding race with mapping change.

Signed-off-by: Chao Yu 
---
v2:
- change to just cover inode lock for f2fs_inline_data_fiemap
 fs/f2fs/data.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index d6302051a65d..12155ee90468 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1150,14 +1150,14 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
if (ret)
return ret;
 
+   inode_lock(inode);
+
if (f2fs_has_inline_data(inode)) {
ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
if (ret != -EAGAIN)
-   return ret;
+   goto out;
}
 
-   inode_lock(inode);
-
if (logical_to_blk(inode, len) == 0)
len = blk_to_logical(inode, 1);
 
-- 
2.15.0.55.gc2ece9dc4de6



[PATCH v2] f2fs: fix to cover f2fs_inline_data_fiemap with inode_lock

2018-01-10 Thread Chao Yu
This patch fix to cover f2fs_inline_data_fiemap with inode_lock in order
to make that interface avoiding race with mapping change.

Signed-off-by: Chao Yu 
---
v2:
- change to just cover inode lock for f2fs_inline_data_fiemap
 fs/f2fs/data.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index d6302051a65d..12155ee90468 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1150,14 +1150,14 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
if (ret)
return ret;
 
+   inode_lock(inode);
+
if (f2fs_has_inline_data(inode)) {
ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
if (ret != -EAGAIN)
-   return ret;
+   goto out;
}
 
-   inode_lock(inode);
-
if (logical_to_blk(inode, len) == 0)
len = blk_to_logical(inode, 1);
 
-- 
2.15.0.55.gc2ece9dc4de6



[tip:perf/core] perf report: Add --tasks option to display monitored tasks

2018-01-10 Thread tip-bot for Jiri Olsa
Commit-ID:  930f8b3479444d264aa33e008c4b00b86e8c62cc
Gitweb: https://git.kernel.org/tip/930f8b3479444d264aa33e008c4b00b86e8c62cc
Author: Jiri Olsa 
AuthorDate: Sun, 7 Jan 2018 17:03:56 +0100
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 10 Jan 2018 12:00:56 -0300

perf report: Add --tasks option to display monitored tasks

Add --tasks option to display monitored tasks stored in perf.data.
Displaying pid/tid/ppid plus the command string aligned to distinguish
parent and child tasks.

  $ perf record -a
  ...
  $ perf report --tasks
  # pid tidppid  comm
  0   0  -1 |swapper
  2   2   0 | kthreadd
  14080   14080   2 |  kworker/u17:1
  4   4   2 |  kworker/0:0H
  6   6   2 |  mm_percpu_wq
  ...
  1   1   0 | systemd
  23242   23242   1 |  firefox
  23242   23298   23242 |   Cache2 I/O
  23242   23304   23242 |   GMPThread
  ...
   11951195   1 |  login
   161116111195 |   bash
   163916391611 |startx
   166316631639 | xinit
   167316731663 |  xmonad-x86_64-l
  23939   239391673 |   xterm
  23941   23941   23939 |bash
  23963   23963   23941 | mutt
  24954   24954   23963 |  offlineimap

Signed-off-by: Jiri Olsa 
Tested-by: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Andi Kleen 
Cc: David Ahern 
Cc: Namhyung Kim 
Cc: Peter Zijlstra 
Link: http://lkml.kernel.org/r/20180107160356.28203-13-jo...@kernel.org
[ Make it --tasks, plural, --task works as well, as its unambiguous ]
[ Use machine__find_thread(), not findnew(), as pointed out by Namhyung ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/Documentation/perf-report.txt |   4 +
 tools/perf/builtin-report.c  | 136 ++-
 2 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt 
b/tools/perf/Documentation/perf-report.txt
index a7d11ef..856c3c7 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -461,6 +461,10 @@ include::itrace.txt[]
Display overall events statistics without any further processing.
(like the one at the end of the perf report -D command)
 
+--tasks::
+   Display monitored tasks stored in perf data. Displaying pid/tid/ppid
+   plus the command string aligned to distinguish parent and child tasks.
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8e67a8c..2c7bd85 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -15,6 +15,7 @@
 #include "util/color.h"
 #include 
 #include 
+#include 
 #include "util/symbol.h"
 #include "util/callchain.h"
 #include "util/values.h"
@@ -63,6 +64,7 @@ struct report {
boolinverted_callchain;
boolmem_mode;
boolstats_mode;
+   booltasks_mode;
boolheader;
boolheader_only;
boolnonany_branch_mode;
@@ -603,6 +605,124 @@ static int stats_print(struct report *rep)
return 0;
 }
 
+static void tasks_setup(struct report *rep)
+{
+   memset(>tool, 0, sizeof(rep->tool));
+   rep->tool.comm = perf_event__process_comm;
+   rep->tool.exit = perf_event__process_exit;
+   rep->tool.fork = perf_event__process_fork;
+   rep->tool.no_warn = true;
+}
+
+struct task {
+   struct thread   *thread;
+   struct list_head list;
+   struct list_head children;
+};
+
+static struct task *tasks_list(struct task *task, struct machine *machine)
+{
+   struct thread *parent_thread, *thread = task->thread;
+   struct task   *parent_task;
+
+   /* Already listed. */
+   if (!list_empty(>list))
+   return NULL;
+
+   /* Last one in the chain. */
+   if (thread->ppid == -1)
+   return task;
+
+   parent_thread = machine__find_thread(machine, -1, thread->ppid);
+   if (!parent_thread)
+   return ERR_PTR(-ENOENT);
+
+   parent_task = thread__priv(parent_thread);
+   list_add_tail(>list, _task->children);
+   return tasks_list(parent_task, machine);
+}
+
+static void task__print_level(struct task *task, FILE *fp, int level)
+{
+   struct thread *thread = task->thread;
+   struct task *child;
+
+   fprintf(fp, "  %8d %8d %8d |%*s%s\n",
+   thread->pid_, thread->tid, thread->ppid,
+   level, "", thread__comm_str(thread));
+
+   if 

[tip:perf/core] perf report: Add --tasks option to display monitored tasks

2018-01-10 Thread tip-bot for Jiri Olsa
Commit-ID:  930f8b3479444d264aa33e008c4b00b86e8c62cc
Gitweb: https://git.kernel.org/tip/930f8b3479444d264aa33e008c4b00b86e8c62cc
Author: Jiri Olsa 
AuthorDate: Sun, 7 Jan 2018 17:03:56 +0100
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 10 Jan 2018 12:00:56 -0300

perf report: Add --tasks option to display monitored tasks

Add --tasks option to display monitored tasks stored in perf.data.
Displaying pid/tid/ppid plus the command string aligned to distinguish
parent and child tasks.

  $ perf record -a
  ...
  $ perf report --tasks
  # pid tidppid  comm
  0   0  -1 |swapper
  2   2   0 | kthreadd
  14080   14080   2 |  kworker/u17:1
  4   4   2 |  kworker/0:0H
  6   6   2 |  mm_percpu_wq
  ...
  1   1   0 | systemd
  23242   23242   1 |  firefox
  23242   23298   23242 |   Cache2 I/O
  23242   23304   23242 |   GMPThread
  ...
   11951195   1 |  login
   161116111195 |   bash
   163916391611 |startx
   166316631639 | xinit
   167316731663 |  xmonad-x86_64-l
  23939   239391673 |   xterm
  23941   23941   23939 |bash
  23963   23963   23941 | mutt
  24954   24954   23963 |  offlineimap

Signed-off-by: Jiri Olsa 
Tested-by: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Andi Kleen 
Cc: David Ahern 
Cc: Namhyung Kim 
Cc: Peter Zijlstra 
Link: http://lkml.kernel.org/r/20180107160356.28203-13-jo...@kernel.org
[ Make it --tasks, plural, --task works as well, as its unambiguous ]
[ Use machine__find_thread(), not findnew(), as pointed out by Namhyung ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/Documentation/perf-report.txt |   4 +
 tools/perf/builtin-report.c  | 136 ++-
 2 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt 
b/tools/perf/Documentation/perf-report.txt
index a7d11ef..856c3c7 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -461,6 +461,10 @@ include::itrace.txt[]
Display overall events statistics without any further processing.
(like the one at the end of the perf report -D command)
 
+--tasks::
+   Display monitored tasks stored in perf data. Displaying pid/tid/ppid
+   plus the command string aligned to distinguish parent and child tasks.
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8e67a8c..2c7bd85 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -15,6 +15,7 @@
 #include "util/color.h"
 #include 
 #include 
+#include 
 #include "util/symbol.h"
 #include "util/callchain.h"
 #include "util/values.h"
@@ -63,6 +64,7 @@ struct report {
boolinverted_callchain;
boolmem_mode;
boolstats_mode;
+   booltasks_mode;
boolheader;
boolheader_only;
boolnonany_branch_mode;
@@ -603,6 +605,124 @@ static int stats_print(struct report *rep)
return 0;
 }
 
+static void tasks_setup(struct report *rep)
+{
+   memset(>tool, 0, sizeof(rep->tool));
+   rep->tool.comm = perf_event__process_comm;
+   rep->tool.exit = perf_event__process_exit;
+   rep->tool.fork = perf_event__process_fork;
+   rep->tool.no_warn = true;
+}
+
+struct task {
+   struct thread   *thread;
+   struct list_head list;
+   struct list_head children;
+};
+
+static struct task *tasks_list(struct task *task, struct machine *machine)
+{
+   struct thread *parent_thread, *thread = task->thread;
+   struct task   *parent_task;
+
+   /* Already listed. */
+   if (!list_empty(>list))
+   return NULL;
+
+   /* Last one in the chain. */
+   if (thread->ppid == -1)
+   return task;
+
+   parent_thread = machine__find_thread(machine, -1, thread->ppid);
+   if (!parent_thread)
+   return ERR_PTR(-ENOENT);
+
+   parent_task = thread__priv(parent_thread);
+   list_add_tail(>list, _task->children);
+   return tasks_list(parent_task, machine);
+}
+
+static void task__print_level(struct task *task, FILE *fp, int level)
+{
+   struct thread *thread = task->thread;
+   struct task *child;
+
+   fprintf(fp, "  %8d %8d %8d |%*s%s\n",
+   thread->pid_, thread->tid, thread->ppid,
+   level, "", thread__comm_str(thread));
+
+   if (!list_empty(>children)) {
+   list_for_each_entry(child, >children, list)
+   task__print_level(child, fp, level + 1);
+   }
+}
+
+static int tasks_print(struct report *rep, FILE *fp)
+{

[tip:perf/core] tools headers: Synchronize kernel <-> tooling headers

2018-01-10 Thread tip-bot for Arnaldo Carvalho de Melo
Commit-ID:  5d64db2966e38bfd99114ecf0b54f97d33023dcd
Gitweb: https://git.kernel.org/tip/5d64db2966e38bfd99114ecf0b54f97d33023dcd
Author: Arnaldo Carvalho de Melo 
AuthorDate: Wed, 10 Jan 2018 11:36:07 -0300
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 10 Jan 2018 12:46:54 -0300

tools headers: Synchronize kernel <-> tooling headers

Two kernel headers got modified recently due to meltdown/spectre, in:

  a89f040fa34e ("x86/cpufeatures: Add X86_BUG_CPU_INSECURE")

which are used by tooling as well:

  arch/x86/include/asm/cpufeatures.h
  arch/x86/include/asm/disabled-features.h

None of those changes have an effect on tooling, so do a plain copy.

Cc: Adrian Hunter 
Cc: David Ahern 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Thomas Gleixner 
Cc: Wang Nan 
Link: https://lkml.kernel.org/n/tip-qqzcs8ri3vks8cypg0puk...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/arch/x86/include/asm/cpufeatures.h   | 4 +++-
 tools/arch/x86/include/asm/disabled-features.h | 8 +++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/tools/arch/x86/include/asm/cpufeatures.h 
b/tools/arch/x86/include/asm/cpufeatures.h
index 800104c..21ac898 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -197,11 +197,12 @@
 #define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation 
Technology L3 */
 #define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation 
Technology L2 */
 #define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data 
Prioritization L3 */
+#define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 7) /* Effectively INVPCID && 
CR4.PCIDE=1 */
 
 #define X86_FEATURE_HW_PSTATE  ( 7*32+ 8) /* AMD HW-PState */
 #define X86_FEATURE_PROC_FEEDBACK  ( 7*32+ 9) /* AMD ProcFeedbackInterface 
*/
 #define X86_FEATURE_SME( 7*32+10) /* AMD Secure Memory 
Encryption */
-
+#define X86_FEATURE_PTI( 7*32+11) /* Kernel Page Table 
Isolation enabled */
 #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory 
Number */
 #define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512_4VNNIW  ( 7*32+16) /* AVX-512 Neural Network 
Instructions */
@@ -340,5 +341,6 @@
 #define X86_BUG_SWAPGS_FENCE   X86_BUG(11) /* SWAPGS without input dep 
on GS */
 #define X86_BUG_MONITORX86_BUG(12) /* IPI required to 
wake up remote CPU */
 #define X86_BUG_AMD_E400   X86_BUG(13) /* CPU is among the 
affected by Erratum 400 */
+#define X86_BUG_CPU_MELTDOWN   X86_BUG(14) /* CPU is affected by 
meltdown attack and needs kernel page table isolation */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/include/asm/disabled-features.h 
b/tools/arch/x86/include/asm/disabled-features.h
index 14d6d50..b027633 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -50,6 +50,12 @@
 # define DISABLE_LA57  (1<<(X86_FEATURE_LA57 & 31))
 #endif
 
+#ifdef CONFIG_PAGE_TABLE_ISOLATION
+# define DISABLE_PTI   0
+#else
+# define DISABLE_PTI   (1 << (X86_FEATURE_PTI & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
@@ -60,7 +66,7 @@
 #define DISABLED_MASK4 (DISABLE_PCID)
 #define DISABLED_MASK5 0
 #define DISABLED_MASK6 0
-#define DISABLED_MASK7 0
+#define DISABLED_MASK7 (DISABLE_PTI)
 #define DISABLED_MASK8 0
 #define DISABLED_MASK9 (DISABLE_MPX)
 #define DISABLED_MASK100


[tip:perf/core] tools headers: Synchronize kernel <-> tooling headers

2018-01-10 Thread tip-bot for Arnaldo Carvalho de Melo
Commit-ID:  5d64db2966e38bfd99114ecf0b54f97d33023dcd
Gitweb: https://git.kernel.org/tip/5d64db2966e38bfd99114ecf0b54f97d33023dcd
Author: Arnaldo Carvalho de Melo 
AuthorDate: Wed, 10 Jan 2018 11:36:07 -0300
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 10 Jan 2018 12:46:54 -0300

tools headers: Synchronize kernel <-> tooling headers

Two kernel headers got modified recently due to meltdown/spectre, in:

  a89f040fa34e ("x86/cpufeatures: Add X86_BUG_CPU_INSECURE")

which are used by tooling as well:

  arch/x86/include/asm/cpufeatures.h
  arch/x86/include/asm/disabled-features.h

None of those changes have an effect on tooling, so do a plain copy.

Cc: Adrian Hunter 
Cc: David Ahern 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Thomas Gleixner 
Cc: Wang Nan 
Link: https://lkml.kernel.org/n/tip-qqzcs8ri3vks8cypg0puk...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/arch/x86/include/asm/cpufeatures.h   | 4 +++-
 tools/arch/x86/include/asm/disabled-features.h | 8 +++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/tools/arch/x86/include/asm/cpufeatures.h 
b/tools/arch/x86/include/asm/cpufeatures.h
index 800104c..21ac898 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -197,11 +197,12 @@
 #define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation 
Technology L3 */
 #define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation 
Technology L2 */
 #define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data 
Prioritization L3 */
+#define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 7) /* Effectively INVPCID && 
CR4.PCIDE=1 */
 
 #define X86_FEATURE_HW_PSTATE  ( 7*32+ 8) /* AMD HW-PState */
 #define X86_FEATURE_PROC_FEEDBACK  ( 7*32+ 9) /* AMD ProcFeedbackInterface 
*/
 #define X86_FEATURE_SME( 7*32+10) /* AMD Secure Memory 
Encryption */
-
+#define X86_FEATURE_PTI( 7*32+11) /* Kernel Page Table 
Isolation enabled */
 #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory 
Number */
 #define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512_4VNNIW  ( 7*32+16) /* AVX-512 Neural Network 
Instructions */
@@ -340,5 +341,6 @@
 #define X86_BUG_SWAPGS_FENCE   X86_BUG(11) /* SWAPGS without input dep 
on GS */
 #define X86_BUG_MONITORX86_BUG(12) /* IPI required to 
wake up remote CPU */
 #define X86_BUG_AMD_E400   X86_BUG(13) /* CPU is among the 
affected by Erratum 400 */
+#define X86_BUG_CPU_MELTDOWN   X86_BUG(14) /* CPU is affected by 
meltdown attack and needs kernel page table isolation */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/include/asm/disabled-features.h 
b/tools/arch/x86/include/asm/disabled-features.h
index 14d6d50..b027633 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -50,6 +50,12 @@
 # define DISABLE_LA57  (1<<(X86_FEATURE_LA57 & 31))
 #endif
 
+#ifdef CONFIG_PAGE_TABLE_ISOLATION
+# define DISABLE_PTI   0
+#else
+# define DISABLE_PTI   (1 << (X86_FEATURE_PTI & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
@@ -60,7 +66,7 @@
 #define DISABLED_MASK4 (DISABLE_PCID)
 #define DISABLED_MASK5 0
 #define DISABLED_MASK6 0
-#define DISABLED_MASK7 0
+#define DISABLED_MASK7 (DISABLE_PTI)
 #define DISABLED_MASK8 0
 #define DISABLED_MASK9 (DISABLE_MPX)
 #define DISABLED_MASK100


  1   2   3   4   5   6   7   8   9   10   >