Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster
>>> > 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
>>> > 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
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
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()
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()
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
(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 LabbeTested-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
(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
(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 LabbeTested-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
(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
(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 LabbeTested-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
(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
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
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
> 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
> 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
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
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
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
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
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 PasternakAcked-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
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
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 PasternakAcked-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
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
It allows driver to run on x86 and ARM architecture based systems. Also some unnecessary includes are removed. Signed-off-by: Vadim PasternakAcked-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
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
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
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
>>> > 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
>>> > 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
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
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
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 Zhaolooks good to me. FWIW, Reviewed-by: Sergey Senozhatsky -ss
Re: [PATCH v3] zswap: only save zswap header when necessary
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
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
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
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
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
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 JeongTested-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
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
==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
==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()
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 ChenTested-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()
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
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
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 ChenTested-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
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 ChenTested-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
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
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
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
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
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
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
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()
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()
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
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
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 ChenTested-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
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
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
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
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
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
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
It'd be safer to enable both FIFOs for TX or RX at the same time. Signed-off-by: Nicolin ChenTested-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
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()
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 ChenTested-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
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 ChenTested-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()
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
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
Since there is a helper function, use it to help readability. Signed-off-by: Nicolin ChenTested-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()
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 ChenTested-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
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()
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()
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 ChenTested-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()
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()
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 ChenTested-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
The cpu_dai_drv is only used for symmetric_rates. So this patch replaces it with a synchronous boolean flag. Signed-off-by: Nicolin ChenTested-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()
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
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
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 ChenTested-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()
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 ChenTested-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
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()
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()
The probe() could handle some one-time configurations since they will not be changed once being configured. Signed-off-by: Nicolin ChenTested-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()
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()
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 ChenTested-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()
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
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
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
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
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
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
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
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
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
Commit-ID: 930f8b3479444d264aa33e008c4b00b86e8c62cc Gitweb: https://git.kernel.org/tip/930f8b3479444d264aa33e008c4b00b86e8c62cc Author: Jiri OlsaAuthorDate: 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
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
Commit-ID: 5d64db2966e38bfd99114ecf0b54f97d33023dcd Gitweb: https://git.kernel.org/tip/5d64db2966e38bfd99114ecf0b54f97d33023dcd Author: Arnaldo Carvalho de MeloAuthorDate: 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
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