Re: [RFC, WIP, v4 06/11] media: vidtv: add wrappers for memcpy and memset
Em Sat, 2 May 2020 08:40:38 +0200 Mauro Carvalho Chehab escreveu: > Em Sat, 2 May 2020 00:22:11 -0300 > "Daniel W. S. Almeida" escreveu: > > > +u32 vidtv_memcpy(void *to, > > +const void *from, > > +size_t len, > > +u32 offset, > > +u32 buf_sz) > > +{ > > + if (buf_sz && offset + len > buf_sz) { > > + pr_err("%s: overflow detected, skipping. Try increasing the > > buffer size", > > + __func__); > > + return 0; > > shouldn't it return an error? > > > + } > > + > > + memcpy(to, from, len); > > + return len; > > +} When trying to use your memset wrapper, I noticed a few issues there. The first one is that you should not use __func__ directly at pr_* macros. Instead, just ensure that you have a pr_fmt() macro that ill be adding the driver's name and the function, e. g.: #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ Besides that, the parameter order sounded weird: > > +u32 vidtv_memcpy(void *to, > > +const void *from, > > +size_t len, > > +u32 offset, > > +u32 buf_sz) The "to", "offset" and "buf_sz" arguments refer to the "to" buffer, while "from" and "len" refers to what will be copied from the "from" into the "to" buffer. Please re-order it, placing first the "to" args, then "from" arg, and finally the argument that applies to both, e. g.: size_t vidtv_memcpy(void *to, size_t to_offset, size_t to_size, const void *from, size_t len) (you should notice that I'm using size_t for all args there). The same is also valid for the memset. Finally, the places where this function is used require to pass twice the offset (from patch 08/11): > + nbytes += vidtv_memcpy(args.dest_buf + > +args.dest_offset + > +nbytes, > +&ts_header, > +sizeof(ts_header), > +args.dest_offset + nbytes, > +args.dest_buf_sz); That doesn't make much sense. I mean, if the arguments are "buf + offset", one would expect that the "buf" would be the head of a buffer, and the function would be adding the offset internally. So, the best would be to re-define it like: /** * vidtv_memcpy() - wrapper routine to be used by MPEG-TS * generator, in order to avoid going past the * output buffer. * @to: Starting element to where a MPEG-TS packet will * be copied. * @to_offset: Starting position of the @to buffer to be filled. * @to_size:Size of the @to buffer. * @from: Starting element of the buffer to be copied. * @ten:Number of elements to be copy from @from buffer * into @to+ @to_offset buffer. * * Note: * Real digital TV demod drivers should not have memcpy * wrappers. We use it here just because emulating a MPEG-TS * generation at kernelspace require some extra care. * * Return: * Returns the number of bytes */ size_t vidtv_memcpy(void *to, size_t to_offset, size_t to_size, const void *from, size_t len) { if unlikely(to_offset + len > to_size) { pr_err_ratelimited("overflow detected, skipping. Try increasing the buffer size\n"); return 0; } memcpy(to + to_offset, from, len); return len; } Thanks, Mauro
答复: [PATCH] [v3] kvm: x86: support APERF/MPERF registers
> -邮件原件- > 发件人: Wei Huang [mailto:wei.hua...@amd.com] > 发送时间: 2020年5月2日 5:31 > 收件人: Li,Rongqing > 抄送: linux-kernel@vger.kernel.org; k...@vger.kernel.org; x...@kernel.org; > h...@zytor.com; b...@alien8.de; mi...@redhat.com; t...@linutronix.de; > jmatt...@google.com; wanpen...@tencent.com; vkuzn...@redhat.com; > sean.j.christopher...@intel.com; pbonz...@redhat.com; xiaoyao...@intel.com > 主题: Re: [PATCH] [v3] kvm: x86: support APERF/MPERF registers > 重要性: 高 > > On 04/30 06:45, Li RongQing wrote: > > Guest kernel reports a fixed cpu frequency in /proc/cpuinfo, this is > > confused to user when turbo is enable, and aperf/mperf can be used to > > show current cpu frequency after 7d5905dc14a > > "(x86 / CPU: Always show current CPU frequency in /proc/cpuinfo)" > > so guest should support aperf/mperf capability > > > > this patch implements aperf/mperf by three mode: none, software > > This > > > emulation, and pass-through > > > > none: default mode, guest does not support aperf/mperf > > > > software emulation: the period of aperf/mperf in guest mode are > > accumulated as emulated value > > > > pass-though: it is only suitable for KVM_HINTS_REALTIME, Because that > > hint guarantees we have a 1:1 vCPU:CPU binding and guaranteed no > > over-commit. > > If we save/restore the values of aperf/mperf properly during vcpu migration > among different cores, is pinning still required? > I think it can be as a new mode, it maybe add more msr operation, like write > > > > and a per-VM capability is added to configure aperfmperf mode > > > > Signed-off-by: Li RongQing > > Signed-off-by: Chai Wen > > Signed-off-by: Jia Lina > > --- > > diff v2: > > support aperfmperf pass though > > move common codes to kvm_get_msr_common > > > > diff v1: > > 1. support AMD, but not test > > pt-mode doesn't work doesn't work on AMD. See below. > > > 2. support per-vm capability to enable Documentation/virt/kvm/api.rst > > | 10 ++ arch/x86/include/asm/kvm_host.h | 11 +++ > > arch/x86/kvm/cpuid.c| 13 - > > arch/x86/kvm/svm.c | 8 > > arch/x86/kvm/vmx/vmx.c | 6 ++ > > arch/x86/kvm/x86.c | 42 > + > > arch/x86/kvm/x86.h | 15 +++ > > include/uapi/linux/kvm.h| 1 + > > 8 files changed, 105 insertions(+), 1 deletion(-) > > > > diff --git a/Documentation/virt/kvm/api.rst > > b/Documentation/virt/kvm/api.rst index efbbe570aa9b..c3be3b6a1717 > > 100644 > > --- a/Documentation/virt/kvm/api.rst > > +++ b/Documentation/virt/kvm/api.rst > > @@ -6109,3 +6109,13 @@ KVM can therefore start protected VMs. > > This capability governs the KVM_S390_PV_COMMAND ioctl and the > > KVM_MP_STATE_LOAD MP_STATE. KVM_SET_MP_STATE can fail for > protected > > guests when the state change is invalid. > > + > > +8.23 KVM_CAP_APERFMPERF > > + > > + > > +:Architectures: x86 > > +:Parameters: args[0] is aperfmperf mode; > > + 0 for not support, 1 for software emulation, 2 for > > +pass-through > > +:Returns: 0 on success; -1 on error > > + > > +This capability indicates that KVM supports APERF and MPERF MSR > > +registers > > diff --git a/arch/x86/include/asm/kvm_host.h > > b/arch/x86/include/asm/kvm_host.h index 42a2d0d3984a..81477f676f60 > > 100644 > > --- a/arch/x86/include/asm/kvm_host.h > > +++ b/arch/x86/include/asm/kvm_host.h > > @@ -820,6 +820,9 @@ struct kvm_vcpu_arch { > > > > /* AMD MSRC001_0015 Hardware Configuration */ > > u64 msr_hwcr; > > + > > + u64 v_mperf; > > + u64 v_aperf; > > }; > > > > struct kvm_lpage_info { > > @@ -885,6 +888,12 @@ enum kvm_irqchip_mode { > > KVM_IRQCHIP_SPLIT,/* created with KVM_CAP_SPLIT_IRQCHIP > */ > > }; > > > > +enum kvm_aperfmperf_mode { > > + KVM_APERFMPERF_NONE, > > + KVM_APERFMPERF_SOFT, /* software emulate aperfmperf */ > > + KVM_APERFMPERF_PT,/* pass-through aperfmperf to guest */ > > +}; > > + > > #define APICV_INHIBIT_REASON_DISABLE0 > > #define APICV_INHIBIT_REASON_HYPERV 1 > > #define APICV_INHIBIT_REASON_NESTED 2 > > @@ -982,6 +991,8 @@ struct kvm_arch { > > > > struct kvm_pmu_event_filter *pmu_event_filter; > > struct task_struct *nx_lpage_recovery_thread; > > + > > + enum kvm_aperfmperf_mode aperfmperf_mode; > > }; > > > > struct kvm_vm_stat { > > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index > > 901cd1fdecd9..7a64ea2c3eef 100644 > > --- a/arch/x86/kvm/cpuid.c > > +++ b/arch/x86/kvm/cpuid.c > > @@ -124,6 +124,14 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) > >MSR_IA32_MISC_ENABLE_MWAIT); > > } > > > > + best = kvm_find_cpuid_entry(vcpu, 6, 0); > > + if (best) { > > + if (guest_has_aperfmperf(vcpu->kvm) && > > + boot_cpu_has(X86_FEATURE_APERFMPERF)) > > + best->ecx |= 1; > > + else > > +
Re: [PATCH 5.6 000/106] 5.6.9-rc1 review
On Sat, May 02, 2020 at 05:14:08PM -0600, shuah wrote: > On 5/1/20 7:22 AM, Greg Kroah-Hartman wrote: > > This is the start of the stable review cycle for the 5.6.9 release. > > There are 106 patches in this series, all will be posted as a response > > to this one. If anyone has any issues with these being applied, please > > let me know. > > > > Responses should be made by Sun, 03 May 2020 13:12:02 +. > > Anything received after that time might be too late. > > > > The whole patch series can be found in one patch at: > > > > https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.6.9-rc1.gz > > or in the git tree and branch at: > > > > git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git > > linux-5.6.y > > and the diffstat can be found below. > > > > thanks, > > > > greg k-h > > > > - > > Compiled and booted on my test system. No dmesg regressions. Thanks for testing all of these and letting me know. greg k-h
Possible memory leak in unxz()
Hi, I am a security researcher, my name is Dongyang Zhan. I found a potential bug. I hope you can help me to confirm it. Thank you. Possible memory leak in Linux 4.10.17. The function unxz() in /lib/decompress_unxz.c forgets to free the pointer 'in', when the statement if (fill == NULL && flush == NULL) is true. Source code and comments: if (in == NULL) { must_free_in = true; in = malloc(XZ_IOBUF_SIZE); if (in == NULL) goto error_alloc_in; } b.in = in; b.in_pos = 0; b.in_size = in_size; b.out_pos = 0; if (fill == NULL && flush == NULL) { ret = xz_dec_run(s, &b); // When this statement is true, it will jumps to the switch statement. But the allocated 'in' is not freed before return. } else { . } . switch (ret) { case XZ_STREAM_END: return 0; case XZ_MEM_ERROR: /* This can occur only in multi-call mode. */ error("XZ decompressor ran out of memory"); break; case XZ_FORMAT_ERROR: error("Input is not in the XZ format (wrong magic bytes)"); break; case XZ_OPTIONS_ERROR: error("Input was encoded with settings that are not " "supported by this XZ decoder"); break; case XZ_DATA_ERROR: case XZ_BUF_ERROR: error("XZ-compressed data is corrupt"); break; default: error("Bug in the XZ decompressor"); break; } return -1;
Re: [PATCH] net: usb: qmi_wwan: add support for DW5816e
Matt Jolly writes: > Add support for Dell Wireless 5816e to drivers/net/usb/qmi_wwan.c > > Signed-off-by: Matt Jolly > --- > drivers/net/usb/qmi_wwan.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c > index 6c738a271257..4bb8552a00d3 100644 > --- a/drivers/net/usb/qmi_wwan.c > +++ b/drivers/net/usb/qmi_wwan.c > @@ -1359,6 +1359,7 @@ static const struct usb_device_id products[] = { > {QMI_FIXED_INTF(0x413c, 0x81b3, 8)},/* Dell Wireless 5809e Gobi(TM) > 4G LTE Mobile Broadband Card (rev3) */ > {QMI_FIXED_INTF(0x413c, 0x81b6, 8)},/* Dell Wireless 5811e */ > {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ > + {QMI_FIXED_INTF(0x413c, 0x81cc, 8)},/* Dell Wireless 5816e */ > {QMI_FIXED_INTF(0x413c, 0x81d7, 0)},/* Dell Wireless 5821e */ > {QMI_FIXED_INTF(0x413c, 0x81d7, 1)},/* Dell Wireless 5821e > preproduction config */ > {QMI_FIXED_INTF(0x413c, 0x81e0, 0)},/* Dell Wireless 5821e with > eSIM support*/ Looks fine to me. Please add to the stable queue as well, Thanks. Acked-by: Bjørn Mork
Re: [PATCH] staging: wilc1000: Increase the size of wid_list array
On Fri, May 01, 2020 at 06:26:10PM +, ajay.kat...@microchip.com wrote: > > On 01/05/20 10:32 pm, Oscar Carter wrote: > > EXTERNAL EMAIL: Do not click links or open attachments unless you know the > > content is safe > > > > Increase by one the size of wid_list array as index variable can reach a > > value of 5. If this happens, an out-of-bounds access is performed. > > > > Addresses-Coverity-ID: 1451981 ("Out-of-bounds access") > > Fixes: c5c77ba18ea66 ("staging: wilc1000: Add SDIO/SPI 802.11 driver") > > The code changes are fine. But the correct commit for Fixes tag should be > > Fixes: f5a3cb90b802d ("staging: wilc1000: add passive scan support") > Sorry for the mistake. I will make the change and I will send a new version. > > Regards, > Ajay > > > Signed-off-by: Oscar Carter > > --- > > drivers/staging/wilc1000/hif.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/staging/wilc1000/hif.c b/drivers/staging/wilc1000/hif.c > > index 6c7de2f8d3f2..128943c3be4f 100644 > > --- a/drivers/staging/wilc1000/hif.c > > +++ b/drivers/staging/wilc1000/hif.c > > @@ -151,7 +151,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 > > scan_type, > > void *user_arg, struct cfg80211_scan_request *request) > > { > > int result = 0; > > - struct wid wid_list[5]; > > + struct wid wid_list[6]; > > u32 index = 0; > > u32 i, scan_timeout; > > u8 *buffer; > > -- > > 2.20.1 > > Thanks, Oscar
Possible null pointer dereference in smp_init_package_map()
Hi, I am a security researcher, my name is Dongyang Zhan. I found a potential bug. I hope you can help me to confirm it. Thank you. In Linux 4.10.17, smp_init_package_map() in /arch/x86/kernel/smpboot.c does not handle the failure of memory allocation, which may cause a null pointer dereference bug. Source code link: https://elixir.bootlin.com/linux/v4.10.17/source/arch/x86/kernel/smpboot.c#L326 Source code and comments: physical_to_logical_pkg = kmalloc(size, GFP_KERNEL); memset(physical_to_logical_pkg, 0xff, size); // does not check if kmalloc fails
Re: [PATCH] staging: gasket: Check the return value of gasket_get_bar_index()
On Sat, May 02, 2020 at 05:59:18PM -0400, Richard Yeh wrote: > Hi, as a new maintainer, I thought I would try to handle this one. Great, as a start: A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail? A: No. Q: Should I include quotations after my reply? http://daringfireball.net/2007/07/on_top > This patch looks good to me. This new check properly protects against using > a negative return value from gasket_get_bar_index() to index into a > pointer. The gasket_get_bar_index function is called in two other places > (old lines 845 and 1044) and both other places check the bar_index return > value for negative values and return error values. > > What is the next step in the process? How do I test the patch? Does Greg > K-H take these patches directly, or is there something else I should do > (looking at > https://github.com/gregkh/presentation-linux-maintainer/blob/master/maintainer.pdf > page > 5: clone from > https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git, ...)? Just send a "Reviewed-by:" to the patch and I can take it from there. Also, I strongly suggest going and talking to your co-maintainers for exactly how to do this, normally at this point in the process you already know this as it is usually an experienced developer doing the maintaining. thanks, greg k-h
Re: [RFC, WIP, v4 08/11] media: vidtv: implement a PSI generator
Em Sat, 2 May 2020 00:22:13 -0300 "Daniel W. S. Almeida" escreveu: > From: "Daniel W. S. Almeida" > > PSI packets contain general information about a MPEG Transport Stream. > A PSI generator is needed so userspace apps can retrieve information > about the Transport Stream and eventually tune into a (dummy) channel. > > Because the generator is implemented in a separate file, it can be > reused elsewhere in the media subsystem. > > Currently this commit adds support for working with 3 PSI tables: > PAT, PMT and SDT. > > Signed-off-by: Daniel W. S. Almeida > --- > drivers/media/test-drivers/vidtv/Makefile|2 +- > drivers/media/test-drivers/vidtv/vidtv_psi.c | 1137 ++ > drivers/media/test-drivers/vidtv/vidtv_psi.h | 357 ++ > 3 files changed, 1495 insertions(+), 1 deletion(-) > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_psi.c > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_psi.h > > diff --git a/drivers/media/test-drivers/vidtv/Makefile > b/drivers/media/test-drivers/vidtv/Makefile > index 92001bc348615..e4f744aa53136 100644 > --- a/drivers/media/test-drivers/vidtv/Makefile > +++ b/drivers/media/test-drivers/vidtv/Makefile > @@ -1,6 +1,6 @@ > # SPDX-License-Identifier: GPL-2.0 > > vidtv_demod-objs := vidtv_common.o > -vidtv_bridge-objs := vidtv_common.o vidtv_ts.o > +vidtv_bridge-objs := vidtv_common.o vidtv_ts.o vidtv_psi.o > > obj-$(CONFIG_DVB_VIDTV) += vidtv_tuner.o vidtv_demod.o vidtv_bridge.o > diff --git a/drivers/media/test-drivers/vidtv/vidtv_psi.c > b/drivers/media/test-drivers/vidtv/vidtv_psi.c > new file mode 100644 > index 0..191d37a248923 > --- /dev/null > +++ b/drivers/media/test-drivers/vidtv/vidtv_psi.c > @@ -0,0 +1,1137 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * This file contains the logic to work with MPEG Program-Specific > Information. > + * These are defined both in ISO/IEC 13818-1 (systems) and ETSI EN 300 468. > + * PSI is carried in the form of table structures, and although each table > might > + * technically be broken into one or more sections, we do not do this here, > + * hence 'table' and 'section' are interchangeable for us. > + * > + * This code currently supports three tables: PAT, PMT and SDT. These are the > + * bare minimum to get userspace to recognize our MPEG transport stream. It > can > + * be extended to support more PSI tables in the future. > + * > + * A note on endianness: MPEG layout is big-endian, therefore: > + * - All fields spanning more than a byte must undergo 'cpu_to_beXX()' before > + * serialization. These convertions are done in the *_write_into() functions. > + * > + * - All byte sized bitfields must have their ordering reversed if > + * __LITTLE_ENDIAN_BITFIELD is defined. > + * > + * Written by: Daniel W. S. Almeida > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "vidtv_psi.h" > +#include "vidtv_common.h" > +#include "vidtv_ts.h" > + > +#define CRC_SIZE_IN_BYTES 4 > + > +static u32 vidtv_psi_ts_psi_write_stuffing(void *to, > +u32 len, > +u32 offset, > +u32 buf_sz) > +{ > + return vidtv_memset(to, 0xff, len, offset, buf_sz); > +} Instead, add thid define: #define TS_FILL_BYTE 0xff And just use vidtv_memset() when needed. > + > +static u32 > +vidtv_psi_ts_psi_write_into(struct psi_write_args args) > +{ > + /* > + * Packetize PSI sections into TS packets: > + * push a TS header (4bytes) every 184 bytes > + * manage the continuity_counter > + * add stuffing after the CRC > + */ > + > + u32 nbytes_past_boundary = (args.dest_offset % TS_PACKET_LEN); > + bool aligned = nbytes_past_boundary == 0; > + > + /* > + * whether we need to fragment the data into multiple ts packets > + * if we are aligned we need to spare one byte for the pointer_field > + */ > + bool split = (aligned) ? > + args.len > TS_PAYLOAD_LEN - 1 : > + nbytes_past_boundary + args.len > TS_PACKET_LEN; > + > + /* how much we can write in this packet */ > + u32 payload_write_len = (split) ? > + (aligned) ? TS_PAYLOAD_LEN : > + TS_PACKET_LEN - nbytes_past_boundary : > + args.len; > + > + struct psi_write_args new_args = {0}; > + struct vidtv_mpeg_ts ts_header = {0}; > + > + u32 nbytes = 0; /* number of bytes written by this function */ > + u32 temp = 0; > + > + /* Just a sanity check, should not really happen because we stuff > + * the packet when we finish a section, i.e. when we write the crc at > + * the end. But if this happens then we have messed up the logic > + * somewhere. > + */ > + WARN_ON(args.new_psi_section && !aligned); Please u
[PATCH v2] staging: wilc1000: Increase the size of wid_list array
Increase by one the size of wid_list array as index variable can reach a value of 5. If this happens, an out-of-bounds access is performed. Addresses-Coverity-ID: 1451981 ("Out-of-bounds access") Fixes: f5a3cb90b802d ("staging: wilc1000: add passive scan support") Signed-off-by: Oscar Carter --- Changelog v1 -> v2 - Fix the commit for the "Fixes" tag as Ajay suggested. drivers/staging/wilc1000/hif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/hif.c b/drivers/staging/wilc1000/hif.c index 6c7de2f8d3f2..128943c3be4f 100644 --- a/drivers/staging/wilc1000/hif.c +++ b/drivers/staging/wilc1000/hif.c @@ -151,7 +151,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, void *user_arg, struct cfg80211_scan_request *request) { int result = 0; - struct wid wid_list[5]; + struct wid wid_list[6]; u32 index = 0; u32 i, scan_timeout; u8 *buffer; -- 2.20.1
Re: [PATCH] pinctrl: qcom: Add affinity callbacks to msmgpio IRQ chip
Quoting Maulik Shah (2020-04-30 23:30:17) > From: Venkata Narendra Kumar Gutta > > Wakeup capable GPIO IRQs routed via PDC are not being migrated when a CPU > is hotplugged. Add affinity callbacks to msmgpio IRQ chip to update the > affinity of wakeup capable IRQs. > > Fixes: e35a6ae0eb3a ("pinctrl/msm: Setup GPIO chip in hierarchy") > Signed-off-by: Venkata Narendra Kumar Gutta > [mkshah: updated commit text and minor code fixes] > Signed-off-by: Maulik Shah > --- Reviewed-by: Stephen Boyd
Re: [PATCH] arm64: dts: qcom: sc7180: Add "no-map" to cmd_db reserved area
Quoting Douglas Anderson (2020-04-24 08:51:29) > The example in the bindings and all the current users (except sc7180) > have "no-map". I'm pretty sure we need it on sc7180 too. Add it. > > Fixes: e0abc5eb526e ("arm64: dts: qcom: sc7180: Add cmd_db reserved area") > Signed-off-by: Douglas Anderson > --- Reviewed-by: Stephen Boyd
RE: [PATCH v4 6/8] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
> - if (!(hba->dev_info.b_wb_buffer_type && > - hba->dev_info.d_wb_alloc_units)) > - goto wb_disabled; > + if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_SHARED) { > + hba->dev_info.d_wb_alloc_units = > + get_unaligned_be32(desc_buf + > + DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS); > + if (!hba->dev_info.d_wb_alloc_units) > + goto wb_disabled; > + } else { > + for (lun = 0; lun < hba->dev_info.max_lu_supported; lun++) { max_lu_supported is determined according to bMaxNumberLU in the geometry descriptor, which can be 32. WB buffer however, is only valid only for LU 0, ..., LU7. Better to add this new limit to ufs.h. > + ret = ufshcd_read_unit_desc_param(hba, > + lun, > + UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS, > + (u8 *)&d_lu_wb_buf_alloc, > + sizeof(d_lu_wb_buf_alloc)); > + if (ret) > + goto wb_disabled; I think you should just continue here, as it is ok for the query to fail. The spec says: The WriteBooster Buffer is available only for the logical units from 0 to 7 which are configured as "normal memory type" (bMemoryType = 00h) and "not Boot well known logical unit" (bBootLunID = 00h), otherwise the Query Request shall fail and the Query Response field shall be set to "General Failure". Sorry for not noticing this earlier. Thanks, Avri > + if (d_lu_wb_buf_alloc) { > + hba->dev_info.wb_dedicated_lu = lun; > + break; > + } > + } > > + if (!d_lu_wb_buf_alloc) > + goto wb_disabled; > + } > return; > > wb_disabled: > diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h > index 898883058e3a..f232a67fd9b3 100644 > --- a/drivers/scsi/ufs/ufshcd.h > +++ b/drivers/scsi/ufs/ufshcd.h > @@ -861,6 +861,13 @@ static inline bool > ufshcd_keep_autobkops_enabled_except_suspend( > return hba->caps & > UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND; > } > > +static inline u8 ufshcd_wb_get_flag_index(struct ufs_hba *hba) > +{ > + if (hba->dev_info.b_wb_buffer_type == > WB_BUF_MODE_LU_DEDICATED) > + return hba->dev_info.wb_dedicated_lu; > + return 0; > +} > + > extern int ufshcd_runtime_suspend(struct ufs_hba *hba); > extern int ufshcd_runtime_resume(struct ufs_hba *hba); > extern int ufshcd_runtime_idle(struct ufs_hba *hba); > -- > 2.18.0
Re: [RFC, WIP, v4 09/11] media: vidtv: implement a PES packetizer
Em Sat, 2 May 2020 00:22:14 -0300 "Daniel W. S. Almeida" escreveu: > From: "Daniel W. S. Almeida" > > Implement the PES logic to convert encoder data into MPEG TS packets. > These TS packets can then be fed into a TS multiplexer and eventually > into userspace. > > Signed-off-by: Daniel W. S. Almeida > --- > drivers/media/test-drivers/vidtv/Makefile | 2 +- > .../media/test-drivers/vidtv/vidtv_common.c | 7 + > .../media/test-drivers/vidtv/vidtv_common.h | 2 + > drivers/media/test-drivers/vidtv/vidtv_pes.c | 429 ++ > drivers/media/test-drivers/vidtv/vidtv_pes.h | 185 > 5 files changed, 624 insertions(+), 1 deletion(-) > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_pes.c > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_pes.h > > diff --git a/drivers/media/test-drivers/vidtv/Makefile > b/drivers/media/test-drivers/vidtv/Makefile > index e4f744aa53136..e3a6540f50e87 100644 > --- a/drivers/media/test-drivers/vidtv/Makefile > +++ b/drivers/media/test-drivers/vidtv/Makefile > @@ -1,6 +1,6 @@ > # SPDX-License-Identifier: GPL-2.0 > > vidtv_demod-objs := vidtv_common.o > -vidtv_bridge-objs := vidtv_common.o vidtv_ts.o vidtv_psi.o > +vidtv_bridge-objs := vidtv_common.o vidtv_ts.o vidtv_psi.o vidtv_pes.o > > obj-$(CONFIG_DVB_VIDTV) += vidtv_tuner.o vidtv_demod.o vidtv_bridge.o > diff --git a/drivers/media/test-drivers/vidtv/vidtv_common.c > b/drivers/media/test-drivers/vidtv/vidtv_common.c > index 28f10630499a9..b1412b497e1e3 100644 > --- a/drivers/media/test-drivers/vidtv/vidtv_common.c > +++ b/drivers/media/test-drivers/vidtv/vidtv_common.c > @@ -42,3 +42,10 @@ u32 vidtv_memset(void *to, > memset(to, c, len); > return len; > } > + > +u64 vidtv_extract_bits(u64 value, u8 start_bit, u8 nbits) > +{ > + u64 mask = ((1 << nbits) - 1) << start_bit; > + > + return value & mask; > +} There are macros already for it, like: include/linux/bits.h:#define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) So, please stick with the existing code there, as defining driver-specific stuff like that is usually painful and may lead into errors. (Btw, your "mask" definition doesn't work with u64) > diff --git a/drivers/media/test-drivers/vidtv/vidtv_common.h > b/drivers/media/test-drivers/vidtv/vidtv_common.h > index 64072c010dc66..3b68f95c5f6c8 100644 > --- a/drivers/media/test-drivers/vidtv/vidtv_common.h > +++ b/drivers/media/test-drivers/vidtv/vidtv_common.h > @@ -25,4 +25,6 @@ u32 vidtv_memset(void *to, >u32 offset, >u32 buf_sz); > > +u64 vidtv_extract_bits(u64 value, u8 start_bit, u8 nbits); > + > #endif // VIDTV_COMMON_H > diff --git a/drivers/media/test-drivers/vidtv/vidtv_pes.c > b/drivers/media/test-drivers/vidtv/vidtv_pes.c > new file mode 100644 > index 0..bc631bac07778 > --- /dev/null > +++ b/drivers/media/test-drivers/vidtv/vidtv_pes.c > @@ -0,0 +1,429 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Vidtv serves as a reference DVB driver and helps validate the existing > APIs > + * in the media subsystem. It can also aid developers working on userspace > + * applications. > + * > + * This file contains the logic to translate the ES data for one access unit > + * from an encoder into MPEG TS packets. It does so by first encapsulating it > + * with a PES header and then splitting it into TS packets. > + * > + * Written by Daniel W. S. Almeida > + */ > + > +#include > +#include > +#include "vidtv_pes.h" > +#include "vidtv_common.h" > +#include "vidtv_ts.h" > + > +#define PRIVATE_STREAM_1_ID 0xbd /* private_stream_1. See SMPTE 302M-2007 > p.6 */ > +#define PES_HEADER_MAX_STUFFING_BYTES 32 > +#define PES_TS_HEADER_MAX_STUFFING_BYTES 182 > + > +static u32 vidtv_pes_op_get_regular_len(bool send_pts, bool send_dts) > +{ > + u32 len = 0; > + > + /* the flags must always be sent */ > + len += sizeof(struct vidtv_pes_optional); > + > + /* From all optionals, we might send these for now */ > + if (send_pts && send_dts) > + len += sizeof(struct vidtv_pes_optional_pts_dts); > + else if (send_pts) > + len += sizeof(struct vidtv_pes_optional_pts); > + > + return len; > +} > + > +static u32 vidtv_pes_h_get_regular_len(bool send_pts, bool send_dts) > +{ > + /* PES header length notwithstanding stuffing bytes */ > + u32 len = 0; > + > + len += sizeof(struct vidtv_mpeg_pes); > + len += vidtv_pes_op_get_regular_len(send_pts, send_dts); > + > + return len; > +} > + > +static u32 vidtv_pes_write_header_stuffing(struct vidtv_mpeg_pes *pes_h, > +struct pes_header_write_args args) > +{ > + /* > + * This is a fixed 8-bit value equal to ' ' that can be inserted > + * by the encoder, for example to meet the requirements of the channel. > + * It is discarded by the decoder. No more than 32 stuffing bytes shall > +
[PATCH] sched/fair: Fix nohz.next_balance update
commit c5afb6a87f23 ("sched/fair: Fix nohz.next_balance update") During idle load balance, this_cpu(ilb) do load balance for the other idle CPUs, also gather the earliest (nohz.)next_balance. Since commit: 'b7031a02ec75 ("sched/fair: Add NOHZ_STATS_KICK")' We update nohz.next_balance like this: _nohz_idle_balance() { for_each_cpu(nohz.idle_cpus_mask) { rebalance_domains() { update nohz.next_balance <-- compare and update } } rebalance_domains(this_cpu) { update nohz.next_balance <-- compare and update } update nohz.next_balance <-- unconditionally update } For instance, nohz.idle_cpus_mask spans {cpu2,3,5,8}, and this_cpu is cpu5. After the above loop we could gather the earliest *next_balance* among {cpu2,3,8}, then rebalance_domains(this_cpu) update nohz.next_balance with this_rq->next_balance, but finally overwrite nohz.next_balance with the earliest *next_balance* among {cpu2,3,8}, we may end up with not getting the earliest next_balance. Since we can gather all the updated rq->next_balance, including this_cpu, in _nohz_idle_balance(), it's safe to remove the extra lines in rebalance_domains() which are originally intended for this_cpu. And finally the updating only happen in _nohz_idle_balance(). Signed-off-by: Peng Liu Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Juri Lelli Cc: Vincent Guittot Cc: Dietmar Eggemann Cc: Steven Rostedt Cc: Ben Segall Cc: Mel Gorman Cc: Valentin Schneider --- kernel/sched/fair.c | 24 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 02f323b85b6d..1d0cf33fefad 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -9943,22 +9943,8 @@ static void rebalance_domains(struct rq *rq, enum cpu_idle_type idle) * When the cpu is attached to null domain for ex, it will not be * updated. */ - if (likely(update_next_balance)) { + if (likely(update_next_balance)) rq->next_balance = next_balance; - -#ifdef CONFIG_NO_HZ_COMMON - /* -* If this CPU has been elected to perform the nohz idle -* balance. Other idle CPUs have already rebalanced with -* nohz_idle_balance() and nohz.next_balance has been -* updated accordingly. This CPU is now running the idle load -* balance for itself and we need to update the -* nohz.next_balance accordingly. -*/ - if ((idle == CPU_IDLE) && time_after(nohz.next_balance, rq->next_balance)) - nohz.next_balance = rq->next_balance; -#endif - } } static inline int on_null_domain(struct rq *rq) @@ -10321,9 +10307,15 @@ static bool _nohz_idle_balance(struct rq *this_rq, unsigned int flags, has_blocked_load |= this_rq->has_blocked_load; } - if (flags & NOHZ_BALANCE_KICK) + if (flags & NOHZ_BALANCE_KICK) { rebalance_domains(this_rq, CPU_IDLE); + if (time_after(next_balance, this_rq->next_balance)) { + next_balance = this_rq->next_balance; + update_next_balance = 1; + } + } + WRITE_ONCE(nohz.next_blocked, now + msecs_to_jiffies(LOAD_AVG_PERIOD)); -- 2.17.1
Re: [PATCH v6 5/5] iio: vcnl4000: Add buffer support for VCNL4010/20.
On Mon, 27 Apr 2020 11:55:59 +0200 Mathieu Othacehe wrote: > The VCNL4010 and VCNL4020 chips are able to raise interrupts on data ready. > Use it to provide triggered buffer support for proximity data. > > Those two chips also provide ambient light data. However, they are sampled > at different rate than proximity data. As this is not handled by the IIO > framework for now, and the sample frequencies of ambient light data are > very low, do add buffer support for them. > > Signed-off-by: Mathieu Othacehe Hi Mathieu, One odd bit of code structure. If you didn't need to respin to fix patch 1's missing sign off I'd just fix it, but pleased tidy it up for v7. Thanks, Jonathan > --- > drivers/iio/light/Kconfig| 2 + > drivers/iio/light/vcnl4000.c | 161 ++- > 2 files changed, 161 insertions(+), 2 deletions(-) > > diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig > index 74970f18a93b..05f61b1e223a 100644 > --- a/drivers/iio/light/Kconfig > +++ b/drivers/iio/light/Kconfig > @@ -506,6 +506,8 @@ config US5182D > > config VCNL4000 > tristate "VCNL4000/4010/4020/4200 combined ALS and proximity sensor" > + select IIO_BUFFER > + select IIO_TRIGGERED_BUFFER > depends on I2C > help > Say Y here if you want to build a driver for the Vishay VCNL4000, > diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c > index 65c0cf2b5037..5f3cc422c371 100644 > --- a/drivers/iio/light/vcnl4000.c > +++ b/drivers/iio/light/vcnl4000.c > @@ -5,6 +5,7 @@ > * > * Copyright 2012 Peter Meerwald > * Copyright 2019 Pursim SPC > + * Copyright 2020 Mathieu Othacehe > * > * IIO driver for: > * VCNL4000/10/20 (7-bit I2C slave address 0x13) > @@ -13,8 +14,7 @@ > * > * TODO: > * allow to adjust IR current > - * periodic ALS/proximity measurement (VCNL4010/20) > - * interrupts (VCNL4010/20/40, VCNL4200) > + * interrupts (VCNL4040, VCNL4200) > */ > > #include > @@ -24,9 +24,13 @@ > #include > #include > > +#include > #include > #include > #include > +#include > +#include > +#include > > #define VCNL4000_DRV_NAME "vcnl4000" > #define VCNL4000_PROD_ID 0x01 > @@ -771,17 +775,26 @@ static const struct iio_chan_spec vcnl4000_channels[] = > { > static const struct iio_chan_spec vcnl4010_channels[] = { > { > .type = IIO_LIGHT, > + .scan_index = -1, > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > BIT(IIO_CHAN_INFO_SCALE), > }, { > .type = IIO_PROXIMITY, > + .scan_index = 0, > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > BIT(IIO_CHAN_INFO_SAMP_FREQ), > .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), > .event_spec = vcnl4000_event_spec, > .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec), > .ext_info = vcnl4000_ext_info, > + .scan_type = { > + .sign = 'u', > + .realbits = 16, > + .storagebits = 16, > + .endianness = IIO_CPU, > + }, > }, > + IIO_CHAN_SOFT_TIMESTAMP(1), > }; > > static const struct iio_info vcnl4000_info = { > @@ -883,10 +896,139 @@ static irqreturn_t vcnl4010_irq_thread(int irq, void > *p) > isr & VCNL4010_INT_THR); > } > > + if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev)) > + iio_trigger_poll_chained(indio_dev->trig); > + > end: > return IRQ_HANDLED; > } > > +static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) > +{ > + struct iio_poll_func *pf = p; > + struct iio_dev *indio_dev = pf->indio_dev; > + struct vcnl4000_data *data = iio_priv(indio_dev); > + const unsigned long *active_scan_mask = indio_dev->active_scan_mask; > + u16 buffer[8] = {0}; /* 1x16-bit + ts */ > + bool data_read = false; > + unsigned long isr; > + int val = 0; > + int ret; > + > + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); > + if (ret < 0) > + goto end; > + > + isr = ret; > + > + if (test_bit(0, active_scan_mask)) { > + if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) { > + ret = vcnl4000_read_data(data, > + VCNL4000_PS_RESULT_HI, > + &val); > + if (ret < 0) > + goto end; > + > + buffer[0] = val; > + data_read = true; > + } > + } > + > + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, > + isr & VCNL4010_INT_DRDY); > + if (ret < 0) > + goto end; > + > + if (!data_read) > + goto end; > + > +
Re: [RFC, WIP, v4 10/11] media: vidtv: Implement a SMPTE 302M encoder
Em Sat, 2 May 2020 00:22:15 -0300 "Daniel W. S. Almeida" escreveu: > From: "Daniel W. S. Almeida" > > Implement a S302M encoder to make it possible to insert PCM audio data > in the generated MPEG Transport Stream. > > This shall enable passing an audio signal into userspace so it can be > decoded and played by media software. > > Signed-off-by: Daniel W. S. Almeida > --- > drivers/media/test-drivers/vidtv/Makefile | 3 +- > .../media/test-drivers/vidtv/vidtv_common.h | 2 + > .../media/test-drivers/vidtv/vidtv_encoder.h | 103 +++ > .../media/test-drivers/vidtv/vidtv_s302m.c| 608 ++ > .../media/test-drivers/vidtv/vidtv_s302m.h| 99 +++ > 5 files changed, 814 insertions(+), 1 deletion(-) > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_encoder.h > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_s302m.c > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_s302m.h > > diff --git a/drivers/media/test-drivers/vidtv/Makefile > b/drivers/media/test-drivers/vidtv/Makefile > index e3a6540f50e87..c916eb19d73bb 100644 > --- a/drivers/media/test-drivers/vidtv/Makefile > +++ b/drivers/media/test-drivers/vidtv/Makefile > @@ -1,6 +1,7 @@ > # SPDX-License-Identifier: GPL-2.0 > > vidtv_demod-objs := vidtv_common.o > -vidtv_bridge-objs := vidtv_common.o vidtv_ts.o vidtv_psi.o vidtv_pes.o > +vidtv_bridge-objs := vidtv_common.o vidtv_ts.o vidtv_psi.o vidtv_pes.o \ > + vidtv_s302m.o > > obj-$(CONFIG_DVB_VIDTV) += vidtv_tuner.o vidtv_demod.o vidtv_bridge.o > diff --git a/drivers/media/test-drivers/vidtv/vidtv_common.h > b/drivers/media/test-drivers/vidtv/vidtv_common.h > index 3b68f95c5f6c8..170646497eb58 100644 > --- a/drivers/media/test-drivers/vidtv/vidtv_common.h > +++ b/drivers/media/test-drivers/vidtv/vidtv_common.h > @@ -13,6 +13,8 @@ > #include > #include > > +#define CLOCK_UNIT_90KHZ 9 > + > u32 vidtv_memcpy(void *to, >const void *from, >size_t len, > diff --git a/drivers/media/test-drivers/vidtv/vidtv_encoder.h > b/drivers/media/test-drivers/vidtv/vidtv_encoder.h > new file mode 100644 > index 0..f483200fd781c > --- /dev/null > +++ b/drivers/media/test-drivers/vidtv/vidtv_encoder.h > @@ -0,0 +1,103 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Vidtv serves as a reference DVB driver and helps validate the existing > APIs > + * in the media subsystem. It can also aid developers working on userspace > + * applications. > + * > + * This file contains a generic encoder type that can provide data for a > stream > + * > + * Written by Daniel W. S. Almeida > + */ > + > +#ifndef VIDTV_ENCODER_H > +#define VIDTV_ENCODER_H > + > +#include > + > +enum vidtv_encoder_id { > + /* add IDs here when implementing new encoders */ > + S302M, > +}; > + > +struct vidtv_encoder { > + /* so we can cast to a concrete implementation when needed */ > + enum vidtv_encoder_id id; > + /* usually same as the stream name */ > + char *name; > + > + /* the encoder's internal buffer for the access units */ > + u8 *encoder_buf; > + /* the encoder buffer size, in bytes */ > + u32 encoder_buf_sz; > + > + /* our byte position in the encoder buffer */ > + u32 encoder_buf_offset; > + > + /* how many samples we have encoded in total */ > + u32 sample_count; > + > + u32 previous_sample_count; > + > + /* the number of access units ready */ > + u32 nunits; > + /* the number of samples per access unit */ > + u32 *samples_per_unit; > + /* pts array mapping pts[i] -> AU[i] */ > + u64 *pts; > + /* dts array mapping dts[i] -> AU[i] */ > + u64 *dts; > + /* array mapping how many bytes were written per AU */ > + u32 *nbytes; > + /* array keeping track of AU offsets in buffer */ > + u32 *offsets; > + > + /* > + * the source of raw data to be encoded, encoder might set a default > + * source if NULL > + */ > + void *src_buf; > + /* the source buffer size, in bytes */ > + u32 src_buf_sz; > + > + /* our byte position in the src buffer */ > + u32 src_buf_offset; > + > + bool video; /* either video or audio */ > + void *ctx; /* encoder-specific state */ > + > + /* Examples: Audio streams (0xc0-0xdf), Video streams (0xe0-0xef) */ > + u16 stream_id; > + > + /* the TS PID to use for the elementary stream in this encoder */ > + u16 es_pid; > + > + /* prepare enough AUs for the given amount of time */ > + void *(*encode)(struct vidtv_encoder *e, u64 elapsed_time_usecs); > + > + /* clear the encoder output */ > + u8 (*clear)(struct vidtv_encoder *e); > + > + /* attempt to synchronize with the encoder below */ > + struct vidtv_encoder *sync; > + > + u32 sampling_rate_hz; /* or fps, if video */ > + > + /* controls dynamic memory allocation for the arrays */ > + u8 access_unit_capacity; > + > + /* >
Re: [PATCH v6 1/5] iio: vcnl4000: Fix i2c swapped word reading.
On Mon, 27 Apr 2020 11:55:55 +0200 Mathieu Othacehe wrote: > The bytes returned by the i2c reading need to be swapped > unconditionally. Otherwise, on be16 platforms, an incorrect value will be > returned. Missing sign off so I can't apply. Also, please add an appropriate fixes tag. Once that's fixed I'll probably be a bit naughty with this one and mark it for stable, but take it for the next merge window. Bug has been there a while without anyone noticing so I don't mind delaying fixing it a little longer to make it easier to merge the rest of the series. Thanks, Jonathan > --- > drivers/iio/light/vcnl4000.c | 6 ++ > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c > index 58e97462e803..e5f86bd00fb0 100644 > --- a/drivers/iio/light/vcnl4000.c > +++ b/drivers/iio/light/vcnl4000.c > @@ -219,7 +219,6 @@ static int vcnl4000_measure(struct vcnl4000_data *data, > u8 req_mask, > u8 rdy_mask, u8 data_reg, int *val) > { > int tries = 20; > - __be16 buf; > int ret; > > mutex_lock(&data->vcnl4000_lock); > @@ -246,13 +245,12 @@ static int vcnl4000_measure(struct vcnl4000_data *data, > u8 req_mask, > goto fail; > } > > - ret = i2c_smbus_read_i2c_block_data(data->client, > - data_reg, sizeof(buf), (u8 *) &buf); > + ret = i2c_smbus_read_word_swapped(data->client, data_reg); > if (ret < 0) > goto fail; > > mutex_unlock(&data->vcnl4000_lock); > - *val = be16_to_cpu(buf); > + *val = ret; > > return 0; >
Re: [PATCH V3 4/4] iio: adc: Update error checks and debug prints
On Mon, 27 Apr 2020 18:54:05 +0530 Jishnu Prakash wrote: > Change pr_err/pr_debug statements to dev_err/dev_dbg for > increased clarity. Also clean up some return value checks. > > Signed-off-by: Jishnu Prakash I'm happy with the whole series. Just need a devicetree review before applying. Thanks, Jonathan > --- > drivers/iio/adc/qcom-spmi-adc5.c | 30 +++--- > 1 file changed, 15 insertions(+), 15 deletions(-) > > diff --git a/drivers/iio/adc/qcom-spmi-adc5.c > b/drivers/iio/adc/qcom-spmi-adc5.c > index a66eeb7..7e951a0 100644 > --- a/drivers/iio/adc/qcom-spmi-adc5.c > +++ b/drivers/iio/adc/qcom-spmi-adc5.c > @@ -249,11 +249,11 @@ static int adc5_read_voltage_data(struct adc5_chip > *adc, u16 *data) > *data = (rslt_msb << 8) | rslt_lsb; > > if (*data == ADC5_USR_DATA_CHECK) { > - pr_err("Invalid data:0x%x\n", *data); > + dev_err(adc->dev, "Invalid data:0x%x\n", *data); > return -EINVAL; > } > > - pr_debug("voltage raw code:0x%x\n", *data); > + dev_dbg(adc->dev, "voltage raw code:0x%x\n", *data); > > return 0; > } > @@ -304,7 +304,7 @@ static int adc5_configure(struct adc5_chip *adc, > > /* Read registers 0x42 through 0x46 */ > ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); > - if (ret < 0) > + if (ret) > return ret; > > /* Digital param selection */ > @@ -344,7 +344,7 @@ static int adc7_configure(struct adc5_chip *adc, > return ret; > > ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); > - if (ret < 0) > + if (ret) > return ret; > > /* Digital param selection */ > @@ -385,24 +385,24 @@ static int adc5_do_conversion(struct adc5_chip *adc, > > ret = adc5_configure(adc, prop); > if (ret) { > - pr_err("ADC configure failed with %d\n", ret); > + dev_err(adc->dev, "ADC configure failed with %d\n", ret); > goto unlock; > } > > if (adc->poll_eoc) { > ret = adc5_poll_wait_eoc(adc); > if (ret < 0) { > - pr_err("EOC bit not set\n"); > + dev_err(adc->dev, "EOC bit not set\n"); > goto unlock; > } > } else { > ret = wait_for_completion_timeout(&adc->complete, > ADC5_CONV_TIMEOUT); > if (!ret) { > - pr_debug("Did not get completion timeout.\n"); > + dev_dbg(adc->dev, "Did not get completion timeout.\n"); > ret = adc5_poll_wait_eoc(adc); > if (ret < 0) { > - pr_err("EOC bit not set\n"); > + dev_err(adc->dev, "EOC bit not set\n"); > goto unlock; > } > } > @@ -435,7 +435,7 @@ static int adc7_do_conversion(struct adc5_chip *adc, > wait_for_completion_timeout(&adc->complete, ADC7_CONV_TIMEOUT); > > ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1); > - if (ret < 0) > + if (ret) > goto unlock; > > if (status & ADC5_USR_STATUS1_CONV_FAULT) { > @@ -481,8 +481,8 @@ static int adc7_of_xlate(struct iio_dev *indio_dev, > int i, v_channel; > > for (i = 0; i < adc->nchannels; i++) { > - v_channel = (adc->chan_props[i].sid << ADC_CHANNEL_OFFSET | > - adc->chan_props[i].channel); > + v_channel = (adc->chan_props[i].sid << ADC_CHANNEL_OFFSET) | > + adc->chan_props[i].channel; > if (v_channel == iiospec->args[0]) > return i; > } > @@ -728,7 +728,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc, > channel_name = of_get_property(node, > "label", NULL) ? : node->name; > if (!channel_name) { > - pr_err("Invalid channel name\n"); > + dev_err(dev, "Invalid channel name\n"); > return -EINVAL; > } > prop->datasheet_name = channel_name; > @@ -766,12 +766,12 @@ static int adc5_get_dt_channel_data(struct adc5_chip > *adc, > > ret = adc5_read(adc, ADC5_USR_REVISION1, dig_version, > sizeof(dig_version)); > - if (ret < 0) { > + if (ret) { > dev_err(dev, "Invalid dig version read %d\n", ret); > return ret; > } > > - pr_debug("dig_ver:minor:%d, major:%d\n", dig_version[0], > + dev_dbg(dev, "dig_ver:minor:%d, major:%d\n", dig_version[0], > dig_version[1]); > /* Digital controller >= 5.3 have hw_settle_2 option */ > if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_
Re: [PATCH v3 6/6] loop: be paranoid on exit and prevent new additions / removals
On Wed, Apr 29, 2020 at 11:50:34AM +0200, Greg KH wrote: > On Wed, Apr 29, 2020 at 07:46:27AM +, Luis Chamberlain wrote: > > Be pedantic on removal as well and hold the mutex. > > This should prevent uses of addition while we exit. > > > > Signed-off-by: Luis Chamberlain > > --- > > drivers/block/loop.c | 4 > > 1 file changed, 4 insertions(+) > > > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c > > index da693e6a834e..6dccba22c9b5 100644 > > --- a/drivers/block/loop.c > > +++ b/drivers/block/loop.c > > @@ -2333,6 +2333,8 @@ static void __exit loop_exit(void) > > > > range = max_loop ? max_loop << part_shift : 1UL << MINORBITS; > > > > + mutex_lock(&loop_ctl_mutex); > > + > > idr_for_each(&loop_index_idr, &loop_exit_cb, NULL); > > idr_destroy(&loop_index_idr); > > > > @@ -2340,6 +2342,8 @@ static void __exit loop_exit(void) > > unregister_blkdev(LOOP_MAJOR, "loop"); > > > > misc_deregister(&loop_misc); > > + > > + mutex_unlock(&loop_ctl_mutex); > > } > > > > module_init(loop_init); > > What type of issue is this helping with? Can it be triggered today? if > so, shouldn't it be backported to stable kernels? Just code inspection. I can't trigger a userspace test script to crash the kernel yet, but suspect a race still does exist. Luis
Re: [RFC, WIP, v4 11/11] media: vidtv: Add a MPEG Transport Stream Multiplexer
Em Sat, 2 May 2020 00:22:16 -0300 "Daniel W. S. Almeida" escreveu: > From: "Daniel W. S. Almeida" > > Add a MPEG Transport Stream multiplexer responsible for polling encoders, > interleaving packets, padding the resulting stream with NULL packets if > necessary and then delivering the resulting TS packets to the bridge > driver so it can feed the demux. > > This patch includes a "channel" abstraction, which attempts to map a > MPEG service into a struct that vidtv can work with. > > When vidtv boots, it will create some hardcoded channels: > > -Their services will be concatenated to populate the SDT. > -Their programs will be concatenated to populate the PAT > -For each program in the PAT, a PMT section will be created > -The PMT section for a channel will be assigned its streams. > -Every stream will have its corresponding encoder polled to produce TS packets > -These packets may be interleaved by the mux and then delivered to the bridg > > Signed-off-by: Daniel W. S. Almeida The same notes I made on previous patches apply here. > --- > drivers/media/test-drivers/vidtv/Makefile | 2 +- > .../media/test-drivers/vidtv/vidtv_bridge.c | 67 ++- > .../media/test-drivers/vidtv/vidtv_bridge.h | 2 + > .../media/test-drivers/vidtv/vidtv_channel.c | 326 ++ > .../media/test-drivers/vidtv/vidtv_channel.h | 66 +++ > .../media/test-drivers/vidtv/vidtv_common.h | 3 + > drivers/media/test-drivers/vidtv/vidtv_mux.c | 423 ++ > drivers/media/test-drivers/vidtv/vidtv_mux.h | 105 + > drivers/media/test-drivers/vidtv/vidtv_psi.c | 18 + > drivers/media/test-drivers/vidtv/vidtv_psi.h | 5 + > 10 files changed, 1014 insertions(+), 3 deletions(-) > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_channel.c > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_channel.h > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_mux.c > create mode 100644 drivers/media/test-drivers/vidtv/vidtv_mux.h > > diff --git a/drivers/media/test-drivers/vidtv/Makefile > b/drivers/media/test-drivers/vidtv/Makefile > index c916eb19d73bb..a1d29001fffe3 100644 > --- a/drivers/media/test-drivers/vidtv/Makefile > +++ b/drivers/media/test-drivers/vidtv/Makefile > @@ -2,6 +2,6 @@ > > vidtv_demod-objs := vidtv_common.o > vidtv_bridge-objs := vidtv_common.o vidtv_ts.o vidtv_psi.o vidtv_pes.o \ > - vidtv_s302m.o > + vidtv_s302m.o vidtv_channel.o vidtv_mux.o > > obj-$(CONFIG_DVB_VIDTV) += vidtv_tuner.o vidtv_demod.o vidtv_bridge.o > diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c > b/drivers/media/test-drivers/vidtv/vidtv_bridge.c > index 05ca4027c869f..c9876372fdebd 100644 > --- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c > +++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c > @@ -13,8 +13,10 @@ > #include > #include > #include "vidtv_bridge.h" > +#include "vidtv_ts.h" > +#include "vidtv_mux.h" > > -#define TS_BUF_MAX_SZ (128 * 188) > +#define TS_BUF_MAX_SZ (128 * TS_PACKET_LEN) > #define TUNER_DEFAULT_ADDR 0x68 > #define DEMOD_DEFAULT_ADDR 0x60 > > @@ -64,16 +66,63 @@ module_param(chosen_delsys, uint, 0644); > MODULE_PARM_DESC(chosen_delsys, >"The delivery system to simulate. Currently supported: DVB-T, > DVB-C, DVB-S"); > > -static unsigned int ts_buf_sz = 20 * 188; > +static unsigned int ts_buf_sz = 20 * TS_PACKET_LEN; > module_param(ts_buf_sz, uint, 0644); > MODULE_PARM_DESC(ts_buf_sz, "Optional size for the TS buffer"); > > DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums); > > +/* > + * Influences the signal acquisition time. See ISO/IEC 13818-1 : 2000. p. > 113. > + */ > +static unsigned int si_period_msec = 40; > +module_param(si_period_msec, uint, 0644); > +MODULE_PARM_DESC(si_period_msec, "How often to send SI packets. Default: > 40ms"); > + > +static unsigned int pcr_period_msec = 40; > +module_param(pcr_period_msec, uint, 0644); > +MODULE_PARM_DESC(pcr_period_msec, "How often to send PCR packets. Default: > 40ms"); > + > +static unsigned int mux_rate_kbytes_sec = 4096; > +module_param(mux_rate_kbytes_sec, uint, 0644); > +MODULE_PARM_DESC(mux_rate_kbytes_sec, "Optional mux rate: will pad stream if > below"); > + > +static unsigned int pcr_pid = 0x200 > +module_param(pcr_pid, uint, 0644); > +MODULE_PARM_DESC(pcr_pid, "Optional PCR PID for all channels: defaults to > 0x200"); > + Same comments I made on a past patch about module parameters apply here. Also, for the last two, I would remove the "Optional" word. All modprobe parameters are optional ;-) > +static bool vidtv_bridge_check_demod_lock(struct vidtv_dvb *dvb, u32 n) > +{ > + enum fe_status status; > + > + dvb->fe[n]->ops.read_status(dvb->fe[n], &status); > + > + return status == FE_HAS_SIGNAL | > + FE_HAS_CARRIER | > + FE_HAS_VITERBI | > + FE_HAS_SYNC| > + FE_HAS_LOCK; > +} > + > +st
Re: [PATCH 2/2] staging: vt6655: fix LONG_LINE warning
On Sat, May 02, 2020 at 10:11:43PM -0700, Joe Perches wrote: On Sun, 2020-05-03 at 00:16 +0200, Matej Dujava wrote: This patch will fix LONG_LINE error from checkpatch, by createing temporary variable so call to the function is not in if/else block. [] diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c [] Sorry, am I missing something here? @@ -164,16 +164,24 @@ s_uGetTxRsvTime( ) { unsigned int uDataTime, uAckTime; + unsigned short basic_rate; uDataTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, cbFrameLength, wRate); if (!bNeedAck) return uDataTime; - if (byPktType == PK_TYPE_11B) /* llb,CCK mode */ - uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopCCKBasicRate); - else /* 11g 2.4G OFDM mode & 11a 5G OFDM mode */ - uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopOFDMBasicRate); + /* +* CCK mode - 11b +* OFDM mode - 11g 2.4G & 11a 5G +*/ + if (byPktType == PK_TYPE_11B) + basic_rate = (unsigned short)pDevice->byTopCCKBasicRate; + else + basic_rate = (unsigned short)pDevice->byTopOFDMBasicRate; + + uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, +basic_rate); return uDataTime + pDevice->uSIFS + uAckTime; } perhaps simpler using a ?: uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, byPktType == PK_TYPE_11B ? pDevice->byTopCCKBasicRate : pDevice->byTopOFDMBasicRate); the casts aren't necessary either as both by... fields are u8 Thank you, will resend my patch.
Re: [GIT PULL] Ressurect the atomisp staging driver
Hi ! Thanks for this, it is very appreciated !! I have a bay trail 2in1 (namely, the acer aspire swtich 10 sw5-012, with an OV2722 module, so supported by the driver) on top of which I run android-x86-q so I would be able to help a bit with testing the driver. I tried to pull in your changes on top of my 5.7-rc2 here : https://gitlab.com/lineageos-x86/android_kernel_common/-/commits/5.7-media but I did not understood how to correctly enable the driver. According to Kconfig help, there is still the hardcoded switch between ISP2401 and ISP2400, so for my Bay Trail tablet I should set : # CONFIG_VIDEO_ATOMISP_ISP2401 is not set but settings this breaks compilation with : ERROR: modpost: "ia_css_configure_sc"[drivers/staging/media/atomisp/atomisp.ko] undefined! Looking at commit history, I noticed that the driver should be able to recognize at runtime the ISP version, so what I tried next was to set CONFIG_VIDEO_ATOMISP_ISP2401=y, and the compilation went fine. I was able to boot the kernel (and I also added both shisp_2400b0_v21.bin and shisp_2401a0_v21.bin from an android tablet dump). The kernel booted fine, the ov2722 module is loaded, but according to dmesg it is not able to initialize the hardware : https://pastebin.com/VBMD1bau Unfortunately I am not too experienced in kernel\driver development but I would be happy to help to debug this, with guidance, if possible. Il giorno ven, 01/05/2020 alle 21.57 +0200, Mauro Carvalho Chehab ha scritto: > This driver is simply too big for it to be sent to the ML via e- > mails. Those > will very likely be rejected due to the e-mail sizes. > > So, instead, I'm sending a "GIT PULL" to myself, at the ML. > > This series basically "resurrect" this driver from the death, giving > it a > second chance to survive. > > I did a lot of cleanups on it during my spare time, and changed it to > be > able to work with ISP2401 (version A0). Several duplicated files got > removed, > several checkpatch warnings solved, and lots of other random things. > > My current plans are to have people at the community testing and > contributing with fixes, while I'll keep focused on cleaning its > code and allow to support all ISP variants at the same time > (right now, it requires a build time decision). > > That's said, I don't have any Atom hardware with cameras myself, and > it > seems that there's at least one version of ISP2401 that may require > some changes (version B0). > > So, we don't know if this works or not, but this also applies to any > other > driver at staging, as warned when someone tries to use it: > > [9.270599] atomisp_ov2680: module is from the staging > directory, the quality is unknown, you have been warned. > [9.350464] atomisp: module is from the staging directory, > the quality is unknown, you have been warned. > > So, use with care. > > Regards, > Mauro > > - > > > The following changes since commit > ceab3ac1e60d70afb4e25147d60817c513f235f7: > > media: dvb-frontends: DUMMY_FE should depends on DVB_CORE (2020-04- > 17 09:21:47 +0200) > > are available in the Git repository at: > > git://linuxtv.org/mchehab/experimental.git atomisp_v2 > > > for you to fetch changes up to > d3151587fa106c2b71169e5ea7d7de799152745f: > > atomisp: remove some file duplication and do more dir renames > (2020-05-01 14:24:58 +0200) > > > Mauro Carvalho Chehab (69): > Revert "media: staging: atomisp: Remove driver" > media: atomisp: fix usage of access_ok() kAPI > media: atomisp: totalram_pages is now a function > media: atomisp: replace VFL_TYPE_GRABBER by VFL_TYPE_VIDEO > media: atomisp: Fix support for time 64 API > media: atomisp: use cpu_latency_qos_*() instead of > pm_qos_update*() > media: atomisp: use new ida API > media: atomisp: fix a broken compat32 code > media: atomisp: allow building the driver again > media: atomisp: fix several typos > media: atomisp: fix several coding style issues > media: atomisp: do lots of other coding style cleanups > media: atomisp: remove some dead code > media: atomisp: simplify math_support.h > media: atomisp: add a way for the driver to know the chipset > version > media: atomisp: atomisp_cmd.c test ISP version in runtime > media: atomisp: atomisp_dfs_tables.h: don't depend on ISP > version > media: atomisp: pci/atomisp2/*.h remove #ifdef ISP2401 > media: atomisp: atomisp_ioctl.c: get rid of a ISP2400/ISP2401 > dependency > media: atomisp: atomisp_v4l2.c: set wdt timers according with > ISP version > media: atomisp: atomisp_subdev.c check ISP version on runtime > media: atomisp: atomisp_csi2.c: remove useless ifdefs > media: atomisp: atomisp_compat_css20.c: detect ISP at runtime > media: atomisp: atomisp_compat_ioctl32.c: be independent of ISP > version > media: atomisp: sh_c
Re: [PATCH 0/4] Introduce the Counter character device interface
On Sat, May 02, 2020 at 05:55:36PM +0100, Jonathan Cameron wrote: > On Fri, 1 May 2020 11:46:10 -0400 > William Breathitt Gray wrote: > > > On Thu, Apr 30, 2020 at 10:13:45PM +0200, Alexandre Belloni wrote: > > > Hi, > > > > > > On 29/04/2020 14:11:34-0400, William Breathitt Gray wrote: > > > > Over the past couple years we have noticed some shortcomings with the > > > > Counter sysfs interface. Although useful in the majority of situations, > > > > there are certain use-cases where interacting through sysfs attributes > > > > can become cumbersome and inefficient. A desire to support more advanced > > > > functionality such as timestamps, multi-axis positioning tables, and > > > > other such latency-sensitive applications, has motivated a reevaluation > > > > of the Counter subsystem. I believe a character device interface will be > > > > helpful for this more niche area of counter device use. > > > > > > > > To quell any concerns from the offset: this patchset makes no changes to > > > > the existing Counter sysfs userspace interface -- existing userspace > > > > applications will continue to work with no modifications necessary. I > > > > request that driver maintainers please test their applications to verify > > > > that this is true, and report any discrepancies if they arise. > > > > > > > > > > On that topic, I'm wondering why the counter subsystem uses /sys/bus > > > instead of /sys/class that would be more natural for a class of devices. > > > I can't see how counters would be considered busses. I think you should > > > consider moving it over to /sys/class (even if deprecating > > > /sys/bus/counter will be long). > > > > At the time I wasn't quite familiar with sysfs development so I was > > following the iio sysfs code rather closely. However, I see now that > > you're probably right: this isn't really a bus but rather a collection > > of various types of counters -- i.e. a class of devices. > > > > Perhaps I should migrate this then to /sys/class/counter. Of course, the > > /sys/bus/counter location will have to remain for compatibility with > > existing applications, but I think a simple symlink to the new > > /sys/class/counter location should suffice for that. > > > > If anyone sees an issue with this give me a heads up. > To just address this point as I've not read the rest of the thread yet... > > I would resist moving it. This one is an old argument. > > Some info in https://lwn.net/Articles/645810/ > As that puts it a "bus" is better known as a "subsystem". > > When we originally considered class vs bus for IIO, the view expressed > at the times was that the whole separation of the two didn't mean anything > and for non trivial cases bus was always preferred. It's nothing to do > with with whether the thing is a bus or not. Now I suppose it's possible > opinion has moved on this topic...However, I'd say there > is really 0 advantage in moving an existing subsystem even if opinion > has changed. > > +CC Greg in case he wants to add anything. Traditionally classes are a unified way of representing data to userspace, independant of the physical transport that the data came to userspace on (i.e. input devices are a class, it doesn't matter if they came on serial, USB, PS/2, or virtual busses.) A bus is traditionally a collection of drivers that all talk on a same physical transport, that then expose data from that transport to a specific userspace class. Again, think USB mice drivers, serial mice drivers, PS/2 mice drivers. Busses bind a driver to a device it creates based on that "bus". Classes create virtual devices that export data to userspace for a specific common protocol. Does that help? One can argue (and have properly in the past), that classes and busses really are not all that different, and there used to be code floating around that made them the same exact thing in the kernel, with loads of userspace sysfs symlinks to preserve things, but those are well out of date and I don't think anyone feels like reviving them. However I think systemd might still have code in it to work properly if that ever happens, haven't looked in a few years... thanks, greg k-h
[PATCH v7 2/5] iio: vcnl4000: Factorize data reading and writing.
Factorize data reading in vcnl4000_measure into a vcnl4000_read_data function. Also add a vcnl4000_write_data function. Signed-off-by: Mathieu Othacehe --- drivers/iio/light/vcnl4000.c | 24 ++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index e5f86bd00fb0..b976e29f2fda 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -215,6 +215,27 @@ static int vcnl4200_init(struct vcnl4000_data *data) return 0; }; +static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val) +{ + s32 ret; + + ret = i2c_smbus_read_word_swapped(data->client, data_reg); + if (ret < 0) + return ret; + + *val = ret; + return 0; +} + +static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val) +{ + if (val > U16_MAX) + return -ERANGE; + + return i2c_smbus_write_word_swapped(data->client, data_reg, val); +} + + static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, u8 rdy_mask, u8 data_reg, int *val) { @@ -245,12 +266,11 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, goto fail; } - ret = i2c_smbus_read_word_swapped(data->client, data_reg); + ret = vcnl4000_read_data(data, data_reg, val); if (ret < 0) goto fail; mutex_unlock(&data->vcnl4000_lock); - *val = ret; return 0; -- 2.26.0
[PATCH v7 1/5] iio: vcnl4000: Fix i2c swapped word reading.
The bytes returned by the i2c reading need to be swapped unconditionally. Otherwise, on be16 platforms, an incorrect value will be returned. Fixes: 62a1efb9f868 ("iio: add vcnl4000 combined ALS and proximity sensor") Signed-off-by: Mathieu Othacehe --- drivers/iio/light/vcnl4000.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 58e97462e803..e5f86bd00fb0 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -219,7 +219,6 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, u8 rdy_mask, u8 data_reg, int *val) { int tries = 20; - __be16 buf; int ret; mutex_lock(&data->vcnl4000_lock); @@ -246,13 +245,12 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, goto fail; } - ret = i2c_smbus_read_i2c_block_data(data->client, - data_reg, sizeof(buf), (u8 *) &buf); + ret = i2c_smbus_read_word_swapped(data->client, data_reg); if (ret < 0) goto fail; mutex_unlock(&data->vcnl4000_lock); - *val = be16_to_cpu(buf); + *val = ret; return 0; -- 2.26.0
[PATCH v7 5/5] iio: vcnl4000: Add buffer support for VCNL4010/20.
The VCNL4010 and VCNL4020 chips are able to raise interrupts on data ready. Use it to provide triggered buffer support for proximity data. Those two chips also provide ambient light data. However, they are sampled at different rate than proximity data. As this is not handled by the IIO framework for now, and the sample frequencies of ambient light data are very low, do add buffer support for them. Signed-off-by: Mathieu Othacehe --- drivers/iio/light/Kconfig| 2 + drivers/iio/light/vcnl4000.c | 161 ++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 74970f18a93b..05f61b1e223a 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -506,6 +506,8 @@ config US5182D config VCNL4000 tristate "VCNL4000/4010/4020/4200 combined ALS and proximity sensor" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER depends on I2C help Say Y here if you want to build a driver for the Vishay VCNL4000, diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 65c0cf2b5037..43b92fc4cab4 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -5,6 +5,7 @@ * * Copyright 2012 Peter Meerwald * Copyright 2019 Pursim SPC + * Copyright 2020 Mathieu Othacehe * * IIO driver for: * VCNL4000/10/20 (7-bit I2C slave address 0x13) @@ -13,8 +14,7 @@ * * TODO: * allow to adjust IR current - * periodic ALS/proximity measurement (VCNL4010/20) - * interrupts (VCNL4010/20/40, VCNL4200) + * interrupts (VCNL4040, VCNL4200) */ #include @@ -24,9 +24,13 @@ #include #include +#include #include #include #include +#include +#include +#include #define VCNL4000_DRV_NAME "vcnl4000" #define VCNL4000_PROD_ID 0x01 @@ -771,17 +775,26 @@ static const struct iio_chan_spec vcnl4000_channels[] = { static const struct iio_chan_spec vcnl4010_channels[] = { { .type = IIO_LIGHT, + .scan_index = -1, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_PROXIMITY, + .scan_index = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .event_spec = vcnl4000_event_spec, .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec), .ext_info = vcnl4000_ext_info, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, }, + IIO_CHAN_SOFT_TIMESTAMP(1), }; static const struct iio_info vcnl4000_info = { @@ -883,10 +896,139 @@ static irqreturn_t vcnl4010_irq_thread(int irq, void *p) isr & VCNL4010_INT_THR); } + if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev)) + iio_trigger_poll_chained(indio_dev->trig); + end: return IRQ_HANDLED; } +static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct vcnl4000_data *data = iio_priv(indio_dev); + const unsigned long *active_scan_mask = indio_dev->active_scan_mask; + u16 buffer[8] = {0}; /* 1x16-bit + ts */ + bool data_read = false; + unsigned long isr; + int val = 0; + int ret; + + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); + if (ret < 0) + goto end; + + isr = ret; + + if (test_bit(0, active_scan_mask)) { + if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) { + ret = vcnl4000_read_data(data, +VCNL4000_PS_RESULT_HI, +&val); + if (ret < 0) + goto end; + + buffer[0] = val; + data_read = true; + } + } + + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, + isr & VCNL4010_INT_DRDY); + if (ret < 0) + goto end; + + if (!data_read) + goto end; + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_get_time_ns(indio_dev)); + +end: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) +{ + struct vcnl4000_data *data = iio_priv(indio_dev); + int ret; + int cmd; + + ret = i
[PATCH v7 0/5] iio: vcnl: Add interrupts support for VCNL4010/20.
Hello, Here's a v7 fixing Jonathan remarks. Thanks, Mathieu Changes from v6: * Add a missing Signed-off" tag in the first commit. * Clean exit pattern in vcnl4010_buffer_postenable. Changes from v5: * Fix i2c measure reads that are broken on the current driver for be16 platforms. * Use read_avail callback for sampling frequency. * Move scan_index setting to the correct patch. Changes from v4: * Rename vcnl4010_in_periodic_mode into vcnl4010_is_in_periodic_mode and vcnl4010_thr_enabled into vcnl4010_is_thr_enabled. Also fix bitmask checking in those functions. * Refactor vcnl4010_write_proxy_samp_freq to loop in the other direction. Changes from v3: * Use i2c_smbus_read_byte_data and i2c_smbus_write_word_data for read and write functions. * Rename vcnl4010_prox_threshold to vcnl4010_config_threshold. * Do not lock i2c accesses as they are already protected. * Fix a typo in irq name. * Do not provide ALS sampling frequency operation, as ALS data are not buffered anymore. * Return bool in vcnl4010_in_periodic_mode and vcnl4010_thr_enabled functions. Changes from v2: * Rebase on iio testing branch. * Remove useless test in vcnl4010_probe_trigger. Changes from v1: * Split into four different patches. * Use iio_device_claim_direct_mode to protect raw access from buffer capture. * Requesting a sampling frequency above the limit is no longer possible. * Inline read_isr and write_isr functions. * Remove IIO_LIGHT data from buffer capture. * Make sure postenable and predisable functions respect the common form. * Do not set the trigger by default. * Remove the devm_iio_triggered_buffer_setup top half. Mathieu Othacehe (5): iio: vcnl4000: Fix i2c swapped word reading. iio: vcnl4000: Factorize data reading and writing. iio: vcnl4000: Add event support for VCNL4010/20. iio: vcnl4000: Add sampling frequency support for VCNL4010/20. iio: vcnl4000: Add buffer support for VCNL4010/20. drivers/iio/light/Kconfig| 2 + drivers/iio/light/vcnl4000.c | 753 --- 2 files changed, 689 insertions(+), 66 deletions(-) -- 2.26.0
[PATCH v7 3/5] iio: vcnl4000: Add event support for VCNL4010/20.
The VCNL4010 and VCNL4020 chips are able to raise interrupts on proximity threshold events. Add support for threshold rising and falling events for those two chips. Signed-off-by: Mathieu Othacehe --- drivers/iio/light/vcnl4000.c | 454 ++- 1 file changed, 392 insertions(+), 62 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index b976e29f2fda..e7653037fa5d 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -13,7 +13,6 @@ * * TODO: * allow to adjust IR current - * proximity threshold and event handling * periodic ALS/proximity measurement (VCNL4010/20) * interrupts (VCNL4010/20/40, VCNL4200) */ @@ -23,7 +22,9 @@ #include #include #include +#include +#include #include #include @@ -35,14 +36,22 @@ #define VCNL4000_COMMAND 0x80 /* Command register */ #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ +#define VCNL4010_PROX_RATE 0x82 /* Proximity rate */ #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */ #define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */ +#define VCNL4010_ALS_PARAM 0x84 /* ALS rate */ #define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */ #define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */ #define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */ #define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */ #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */ +#define VCNL4010_INT_CTRL 0x89 /* Interrupt control */ #define VCNL4000_PS_MOD_ADJ0x8a /* Proximity modulator timing adjustment */ +#define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */ +#define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */ +#define VCNL4010_HIGH_THR_HI0x8c /* High threshold, MSB */ +#define VCNL4010_HIGH_THR_LO0x8d /* High threshold, LSB */ +#define VCNL4010_ISR 0x8e /* Interrupt status */ #define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */ #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */ @@ -57,6 +66,26 @@ #define VCNL4000_PS_RDYBIT(5) /* proximity data ready? */ #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ +#define VCNL4000_ALS_ENBIT(2) /* start ALS measurement */ +#define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */ +#define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */ + +/* Bit masks for interrupt registers. */ +#define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */ +#define VCNL4010_INT_THR_ENBIT(1) /* Threshold interrupt type */ +#define VCNL4010_INT_ALS_ENBIT(2) /* Enable on ALS data ready */ +#define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */ + +#define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */ +#define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */ +#define VCNL4010_INT_ALS 2 /* ALS data ready */ +#define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */ + +#define VCNL4010_INT_THR \ + (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH)) +#define VCNL4010_INT_DRDY \ + (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS)) + #define VCNL4000_SLEEP_DELAY_MS2000 /* before we enter pm_runtime_suspend */ @@ -88,6 +117,10 @@ struct vcnl4000_data { struct vcnl4000_chip_spec { const char *prod; + struct iio_chan_spec const *channels; + const int num_channels; + const struct iio_info *info; + bool irq_support; int (*init)(struct vcnl4000_data *data); int (*measure_light)(struct vcnl4000_data *data, int *val); int (*measure_proximity)(struct vcnl4000_data *data, int *val); @@ -330,67 +363,16 @@ static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) return vcnl4200_measure(data, &data->vcnl4200_ps, val); } -static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { - [VCNL4000] = { - .prod = "VCNL4000", - .init = vcnl4000_init, - .measure_light = vcnl4000_measure_light, - .measure_proximity = vcnl4000_measure_proximity, - .set_power_state = vcnl4000_set_power_state, - }, - [VCNL4010] = { - .prod = "VCNL4010/4020", - .init = vcnl4000_init, - .measure_light = vcnl4000_measure_light, - .measure_proximity = vcnl4000_measure_proximity, - .set_power_state = vcnl4000_set_power_state, - }, - [VCNL4040] = { - .prod = "VCNL4040", - .init = vcnl4200_init, - .measure_light = vcnl4200_measure_light, - .measure_proximi
[PATCH v7 4/5] iio: vcnl4000: Add sampling frequency support for VCNL4010/20.
Add sampling frequency support for proximity data on VCNL4010 and VCNL4020 chips. Signed-off-by: Mathieu Othacehe --- drivers/iio/light/vcnl4000.c | 118 ++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index e7653037fa5d..65c0cf2b5037 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -86,6 +86,16 @@ #define VCNL4010_INT_DRDY \ (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS)) +static const int vcnl4010_prox_sampling_frequency[][2] = { + {1, 95}, + {3, 906250}, + {7, 812500}, + {16, 625000}, + {31, 25}, + {62, 50}, + {125, 0}, + {250, 0}, +}; #define VCNL4000_SLEEP_DELAY_MS2000 /* before we enter pm_runtime_suspend */ @@ -363,6 +373,24 @@ static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) return vcnl4200_measure(data, &data->vcnl4200_ps, val); } +static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val, +int *val2) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE); + if (ret < 0) + return ret; + + if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency)) + return -EINVAL; + + *val = vcnl4010_prox_sampling_frequency[ret][0]; + *val2 = vcnl4010_prox_sampling_frequency[ret][1]; + + return 0; +} + static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data) { int ret; @@ -456,11 +484,95 @@ static int vcnl4010_read_raw(struct iio_dev *indio_dev, iio_device_release_direct_mode(indio_dev); return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_PROXIMITY: + ret = vcnl4010_read_proxy_samp_freq(data, val, val2); + if (ret < 0) + return ret; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } default: return -EINVAL; } } +static int vcnl4010_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = (int *)vcnl4010_prox_sampling_frequency; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val, + int val2) +{ + unsigned int i; + int index = -1; + + for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) { + if (val == vcnl4010_prox_sampling_frequency[i][0] && + val2 == vcnl4010_prox_sampling_frequency[i][1]) { + index = i; + break; + } + } + + if (index < 0) + return -EINVAL; + + return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE, +index); +} + +static int vcnl4010_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret; + struct vcnl4000_data *data = iio_priv(indio_dev); + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + /* Protect against event capture. */ + if (vcnl4010_is_in_periodic_mode(data)) { + ret = -EBUSY; + goto end; + } + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_PROXIMITY: + ret = vcnl4010_write_proxy_samp_freq(data, val, val2); + goto end; + default: + ret = -EINVAL; + goto end; + } + default: + ret = -EINVAL; + goto end; + } + +end: + iio_device_release_direct_mode(indio_dev); + return ret; +} + static int vcnl4010_read_event(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -663,7 +775,9 @@ static const struct iio_chan_spec vcnl4010_channels[] = { BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_PROXIMITY, - .info_mask
Re: [PATCH v6 5/5] iio: vcnl4000: Add buffer support for VCNL4010/20.
Hi Jonathan, > One odd bit of code structure. If you didn't need to respin to fix > patch 1's missing sign off I'd just fix it, but pleased tidy it up for v7. Ok, fixed that in v7! Thanks, Mathieu
Re: [RFC, WIP, v4 07/11] media: vidtv: add MPEG TS common code
Em Sat, 2 May 2020 19:22:06 -0300 "Daniel W. S. Almeida" escreveu: > Hi Mauro, thanks for reviewing this! > > > Em Sat, 2 May 2020 00:22:12 -0300 > > "Daniel W. S. Almeida" escreveu: > > > >> From: "Daniel W. S. Almeida" > >> > >> Add code to work with MPEG TS packets, such as TS headers, adaptation > >> fields, PCR packets and NULL packets. > >> > >> Signed-off-by: Daniel W. S. Almeida > >> --- > >> drivers/media/test-drivers/vidtv/Makefile | 2 +- > >> drivers/media/test-drivers/vidtv/vidtv_ts.c | 130 > >> drivers/media/test-drivers/vidtv/vidtv_ts.h | 103 > >> 3 files changed, 234 insertions(+), 1 deletion(-) > >> create mode 100644 drivers/media/test-drivers/vidtv/vidtv_ts.c > >> create mode 100644 drivers/media/test-drivers/vidtv/vidtv_ts.h > >> > >> diff --git a/drivers/media/test-drivers/vidtv/Makefile > b/drivers/media/test-drivers/vidtv/Makefile > >> index 9ea9485d42189..92001bc348615 100644 > >> --- a/drivers/media/test-drivers/vidtv/Makefile > >> +++ b/drivers/media/test-drivers/vidtv/Makefile > >> @@ -1,6 +1,6 @@ > >> # SPDX-License-Identifier: GPL-2.0 > >> > >> vidtv_demod-objs := vidtv_common.o > >> -vidtv_bridge-objs := vidtv_common.o > >> +vidtv_bridge-objs := vidtv_common.o vidtv_ts.o > >> > >> obj-$(CONFIG_DVB_VIDTV) += vidtv_tuner.o vidtv_demod.o vidtv_bridge.o > >> diff --git a/drivers/media/test-drivers/vidtv/vidtv_ts.c > b/drivers/media/test-drivers/vidtv/vidtv_ts.c > >> new file mode 100644 > >> index 0..f545c45c0fe7c > >> --- /dev/null > >> +++ b/drivers/media/test-drivers/vidtv/vidtv_ts.c > >> @@ -0,0 +1,130 @@ > >> +// SPDX-License-Identifier: GPL-2.0 > >> +/* > >> + * The Virtual DVB test driver serves as a reference DVB driver and > helps > >> + * validate the existing APIs in the media subsystem. It can also aid > >> + * developers working on userspace applications. > >> + * > >> + * Written by Daniel W. S. Almeida > >> + */ > >> + > >> +#include > >> +#include > >> +#include "vidtv_ts.h" > >> +#include "vidtv_common.h" > >> + > >> +static u32 vidtv_ts_write_pcr_bits(u8 *buf, u64 pcr) > >> +{ > >> + /* Exact same from ffmpeg. PCR is a counter driven by a 27Mhz clock */ > >> + u64 pcr_low = pcr % 300, pcr_high = pcr / 300; > >> + > >> + *buf++ = pcr_high >> 25; > >> + *buf++ = pcr_high >> 17; > >> + *buf++ = pcr_high >> 9; > >> + *buf++ = pcr_high >> 1; > >> + *buf++ = pcr_high << 7 | pcr_low >> 8 | 0x7e; > >> + *buf++ = pcr_low; > >> + > >> + return 6; > >> +} > >> + > >> +void vidtv_ts_inc_cc(u8 *continuity_counter) > >> +{ > >> + ++*continuity_counter; > >> + if (*continuity_counter > TS_CC_MAX_VAL) > >> + *continuity_counter = 0; > >> +} > >> + > >> +u32 vidtv_ts_null_write_into(struct null_packet_write_args args) > >> +{ > >> + u32nbytes = 0; > >> + struct vidtv_mpeg_ts ts_header = {0}; > >> + > >> + ts_header.sync_byte = TS_SYNC_BYTE; > >> + ts_header.pid= TS_NULL_PACKET_PID; > >> + ts_header.payload= 1; > >> + ts_header.continuity_counter = *args.continuity_counter; > >> + > >> + cpu_to_be16s(&ts_header.bitfield); > >> + > >> + /* copy TS header */ > >> + nbytes += vidtv_memcpy(args.dest_buf + args.dest_offset + nbytes, > >> +&ts_header, > >> +sizeof(ts_header), > >> +args.dest_offset + nbytes, > >> +args.buf_sz); > > > > Hmm... now I see why you're returning 0 to vidtv_memcpy(). > > > > Yet, if the buffer is full, you should just drop the entire package, > > as otherwise you may end copying things that aren't multiple of 188 > bytes, > > causing sync issues at the client. > > I'd like to provide a counterargument for this. > > The way I am dealing with errors throughout vidtv so far is: > If we hit any of these WARN_ON macros, pr_err and the like, then all > bets are off. This means that the resulting stream will likely be > invalid Losing some data is not really a big issue. I mean, a stream with some dropped packages is acceptable. That actually happens in practice, as sometimes userspace just can't read everything in time. The only thing is that, if buffer overflow conditions are detected (and allowed - se more below), the code should ensure that the package counters should be updated, so the next frame will show a discontinuity. This way, userspace can detect packet losses. > and that something needs to be rewritten in the source code and > my main concern is then preventing the whole driver from crashing. A WARN_ON() won't prevent a crash. It will just output (very noisly) stuff at dmesg. This can actually cause a crash: if someone is using a serial console, for example, the amount of data at dmesg will be so much that the machine will become unresponsive. Btw, when WARN_ON() is detecting something t
Re: [GIT PULL] Ressurect the atomisp staging driver
Hi Francescodario, Em Sun, 3 May 2020 09:19:55 + Francescodario Cuzzocrea escreveu: > Hi ! > > Thanks for this, it is very appreciated !! > > I have a bay trail 2in1 (namely, the acer aspire swtich 10 sw5-012, > with an OV2722 module, so supported by the driver) on top of which I > run android-x86-q so I would be able to help a bit with testing the > driver. > > I tried to pull in your changes on top of my 5.7-rc2 here : > https://gitlab.com/lineageos-x86/android_kernel_common/-/commits/5.7-media > > but I did not understood how to correctly enable the driver. > According > to Kconfig help, there is still the hardcoded switch between ISP2401 > and ISP2400, so for my Bay Trail tablet I should set : > > # > CONFIG_VIDEO_ATOMISP_ISP2401 is not set > > but settings this breaks compilation with : > > ERROR: modpost: > "ia_css_configure_sc"[drivers/staging/media/atomisp/atomisp.ko] > undefined! I'll double check and address this issue. > > Looking at commit history, I noticed that the driver should be able to > recognize at runtime the ISP version, Not yet. There are simply too many places there with checks for ISP2400 or ISP2401. I got rid of most of them, but there are 4 header files that contain ISP-version specific information, whose are used by several parts of the driver. Getting rid of it would require more work. > so what I tried next was to set > CONFIG_VIDEO_ATOMISP_ISP2401=y, and the compilation went fine. > I was able to boot the kernel (and I also added both > shisp_2400b0_v21.bin and shisp_2401a0_v21.bin from an android tablet > dump). > > The kernel booted fine, the ov2722 module is loaded, but according to > dmesg it is not able to initialize the hardware : > https://pastebin.com/VBMD1bau (transcribing the relevant messages from pastebin below) > ov2722 i2c-INT33FB: 00: gmin: initializing atomisp module subdev data.PMIC ID > 1 > ov2722 i2c-INT33FB: 00: supply V1P2A not found, using dummy regulator > ov2722 i2c-INT33FB: 00: supply VPROG4B not found, using dummy regulator > ov2722 i2c-INT33FB: 00: supply Regulator1p8v not found, using dummy regulator > ov2722 i2c-INT33FB: 00: supply Regulator2p8v not found, using dummy regulator > ov2722 i2c-INT33FB: 00: unable to set PMC rate 1 > ov2722 i2c-INT33FB: 00: camera pdata: port: 0 lanes: 1 order: > ov2722 i2c-INT33FB: 00: read from offset 0x300a error -121 > ov2722 i2c-INT33FB: 00: sensor_id_high = 0x > ov2722 i2c-INT33FB: 00: ov2722_detect err s_config. > ov2722 i2c-INT33FB: 00: sensor power-gating failed That's the same that happened with the tests we've done so far: it is not finding the regulators. I'm currently seeking for a solution to that. Usually, regulator data comes via OpenFirmware/Device Tree. However, ACPI BIOS store this on a different way. Some (missing) code would need to get the relevant parameters from the BIOS and setup the regulators. Btw, could you please send me a tarball with the output of your BIOS ACPI tables? You can get it with: $ sudo acpidump |bzip2 > acpi.log.bz2 Thanks, Mauro
Re: [PATCH v7 0/5] KUnit-KASAN Integration
On Thu, 23 Apr 2020, David Gow wrote: > This patchset contains everything needed to integrate KASAN and KUnit. > > KUnit will be able to: > (1) Fail tests when an unexpected KASAN error occurs > (2) Pass tests when an expected KASAN error occurs > > Convert KASAN tests to KUnit with the exception of copy_user_test > because KUnit is unable to test those. > > Add documentation on how to run the KASAN tests with KUnit and what to > expect when running these tests. > > This patchset depends on: > - "[PATCH v3 kunit-next 0/2] kunit: extend kunit resources API" [1] > - "[PATCH v3 0/3] Fix some incompatibilites between KASAN and > FORTIFY_SOURCE" [2] > > Changes from v6: > - Rebased on top of kselftest/kunit > - Rebased on top of Daniel Axtens' fix for FORTIFY_SOURCE >incompatibilites [2] > - Removed a redundant report_enabled() check. > - Fixed some places with out of date Kconfig names in the >documentation. > Sorry for the delay in getting to this; I retested the series with the above patchsets pre-applied; all looks good now, thanks! Looks like Daniel's patchset has a v4 so I'm not sure if that will have implications for applying your changes on top of it (haven't tested it yet myself). For the series feel free to add Tested-by: Alan Maguire I'll try and take some time to review v7 shortly, but I wanted to confirm the issues I saw went away first in case you're blocked. The only remaining issue I see is that we'd need the named resource patchset to land first; it would be good to ensure the API it provides is solid so you won't need to respin. Thanks! Alan > Changes from v5: > - Split out the panic_on_warn changes to a separate patch. > - Fix documentation to fewer to the new Kconfig names. > - Fix some changes which were in the wrong patch. > - Rebase on top of kselftest/kunit (currently identical to 5.7-rc1) > > Changes from v4: > - KASAN no longer will panic on errors if both panic_on_warn and >kasan_multishot are enabled. > - As a result, the KASAN tests will no-longer disable panic_on_warn. > - This also means panic_on_warn no-longer needs to be exported. > - The use of temporary "kasan_data" variables has been cleaned up >somewhat. > - A potential refcount/resource leak should multiple KASAN errors >appear during an assertion was fixed. > - Some wording changes to the KASAN test Kconfig entries. > > Changes from v3: > - KUNIT_SET_KASAN_DATA and KUNIT_DO_EXPECT_KASAN_FAIL have been > combined and included in KUNIT_DO_EXPECT_KASAN_FAIL() instead. > - Reordered logic in kasan_update_kunit_status() in report.c to be > easier to read. > - Added comment to not use the name "kasan_data" for any kunit tests > outside of KUNIT_EXPECT_KASAN_FAIL(). > > Changes since v2: > - Due to Alan's changes in [1], KUnit can be built as a module. > - The name of the tests that could not be run with KUnit has been > changed to be more generic: test_kasan_module. > - Documentation on how to run the new KASAN tests and what to expect > when running them has been added. > - Some variables and functions are now static. > - Now save/restore panic_on_warn in a similar way to kasan_multi_shot > and renamed the init/exit functions to be more generic to accommodate. > - Due to [3] in kasan_strings, kasan_memchr, and > kasan_memcmp will fail if CONFIG_AMD_MEM_ENCRYPT is enabled so return > early and print message explaining this circumstance. > - Changed preprocessor checks to C checks where applicable. > > Changes since v1: > - Make use of Alan Maguire's suggestion to use his patch that allows >static resources for integration instead of adding a new attribute to >the kunit struct > - All KUNIT_EXPECT_KASAN_FAIL statements are local to each test > - The definition of KUNIT_EXPECT_KASAN_FAIL is local to the >test_kasan.c file since it seems this is the only place this will >be used. > - Integration relies on KUnit being builtin > - copy_user_test has been separated into its own file since KUnit >is unable to test these. This can be run as a module just as before, >using CONFIG_TEST_KASAN_USER > - The addition to the current task has been separated into its own >patch as this is a significant enough change to be on its own. > > > [1] > https://lore.kernel.org/linux-kselftest/1585313122-26441-1-git-send-email-alan.magu...@oracle.com/T/#t > [2] https://lkml.org/lkml/2020/4/23/708 > [3] https://bugzilla.kernel.org/show_bug.cgi?id=206337 > > > > David Gow (1): > mm: kasan: Do not panic if both panic_on_warn and kasan_multishot set > > Patricia Alfonso (4): > Add KUnit Struct to Current Task > KUnit: KASAN Integration > KASAN: Port KASAN Tests to KUnit > KASAN: Testing Documentation > > Documentation/dev-tools/kasan.rst | 70 +++ > include/kunit/test.h | 5 + > include/linux/kasan.h | 6 + > include/linux/sched.h | 4 + > lib/Kconfig.kasan | 18 +- > lib/
Re: [PATCH] epoll: ensure ep_poll() doesn't miss wakeup events
On 2020-05-02 00:09, Jason Baron wrote: On 5/1/20 5:02 PM, Roman Penyaev wrote: Hi Jason, That is indeed a nice catch. Seems we need smp_rmb() pair between list_empty_careful(&rp->rdllist) and READ_ONCE(ep->ovflist) for ep_events_available(), do we? Hi Roman, Good point, even if we order those reads its still racy, since the read of the ready list could come after its been cleared and the read of the overflow could again come after its been cleared. You mean the second chunk? True. Sigh. So I'm afraid we might need instead something like this to make sure they are read together: No, impossible, I can't believe in that :) We can't give up. All we need is to keep a mark, that ep->rdllist is not empty, even we've just spliced it. ep_poll_callback() always takes the ->ovflist path, if ->ovflist is not EP_UNACTIVE_PTR, but ep_events_available() does not need to observe ->ovflist at all, just a ->rdllist. Take a look at that, do I miss something? : diff --git a/fs/eventpoll.c b/fs/eventpoll.c index aba03ee749f8..a8770f9a917e 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -376,8 +376,7 @@ static void ep_nested_calls_init(struct nested_calls *ncalls) */ static inline int ep_events_available(struct eventpoll *ep) { - return !list_empty_careful(&ep->rdllist) || - READ_ONCE(ep->ovflist) != EP_UNACTIVE_PTR; + return !list_empty_careful(&ep->rdllist); } #ifdef CONFIG_NET_RX_BUSY_POLL @@ -683,7 +682,8 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep, { __poll_t res; struct epitem *epi, *nepi; - LIST_HEAD(txlist); + LIST_HEAD(rdllist); + LIST_HEAD(ovflist); lockdep_assert_irqs_enabled(); @@ -704,14 +704,22 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep, * in a lockless way. */ write_lock_irq(&ep->lock); - list_splice_init(&ep->rdllist, &txlist); + /* +* We do not call list_splice_init() because for lockless +* ep_events_available() ->rdllist is still "not empty". +* Otherwise the feature that there is something left in +* the list can be lost which causes missed wakeup. +*/ + list_splice(&ep->rdllist, &rdllist); + /* +* If ->rdllist was empty we should pretend it was not, +* because after the unlock ->ovflist comes into play, +* which is invisible for lockless ep_events_available(). +*/ + ep->rdllist.next = LIST_POISON1; WRITE_ONCE(ep->ovflist, NULL); write_unlock_irq(&ep->lock); /* * Now call the callback function. */ - res = (*sproc)(ep, &txlist, priv); + res = (*sproc)(ep, &rdllist, priv); write_lock_irq(&ep->lock); /* @@ -724,7 +732,7 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep, /* * We need to check if the item is already in the list. * During the "sproc" callback execution time, items are -* queued into ->ovflist but the "txlist" might already +* queued into ->ovflist but the "rdllist" might already * contain them, and the list_splice() below takes care of them. */ if (!ep_is_linked(epi)) { @@ -732,7 +740,7 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep, * ->ovflist is LIFO, so we have to reverse it in order * to keep in FIFO. */ - list_add(&epi->rdllink, &ep->rdllist); + list_add(&epi->rdllink, &ovflist); ep_pm_stay_awake(epi); } } @@ -743,10 +751,11 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep, */ WRITE_ONCE(ep->ovflist, EP_UNACTIVE_PTR); - /* -* Quickly re-inject items left on "txlist". -*/ - list_splice(&txlist, &ep->rdllist); + /* Events from ->ovflist happened later, thus splice to the tail */ + list_splice_tail(&ovflist, &rdllist); + /* Just replace list */ + list_replace(&rdllist, &ep->rdllist); + __pm_relax(ep->ws); write_unlock_irq(&ep->lock); @@ -1763,13 +1772,13 @@ static __poll_t ep_send_events_proc(struct eventpoll *ep, struct list_head *head * Trigger mode, we need to insert back inside * the ready list, so that the next call to * epoll_wait() will check again the events -* availability. At this point, no one can insert -* into ep->rdllist besides us. The epoll_ctl() -* callers are locked out by -* ep_scan_ready_list() holding "mtx" and the -* poll callback will queue them in ep->ovflist. +* availability. What we do here is sim
[PATCH] x86/tlb/uv: Add a forward declaration for struct flush_tlb_info
From: Borislav Petkov ... to fix these build warnings: In file included from ./arch/x86/include/asm/uv/uv_hub.h:22, from drivers/misc/sgi-gru/grukdump.c:16: ./arch/x86/include/asm/uv/uv.h:39:21: warning: ‘struct flush_tlb_info’ declared \ inside parameter list will not be visible outside of this definition or declaration 39 |const struct flush_tlb_info *info); | ^~ In file included from ./arch/x86/include/asm/uv/uv_hub.h:22, from drivers/misc/sgi-gru/grutlbpurge.c:28: ./arch/x86/include/asm/uv/uv.h:39:21: warning: ‘struct flush_tlb_info’ declared \ inside parameter list will not be visible outside of this definition or declaration 39 |const struct flush_tlb_info *info); | ^~ ... after bfe3d8f6313d ("x86/tlb: Restrict access to tlbstate") restricted access to tlbstate. Signed-off-by: Borislav Petkov --- arch/x86/include/asm/uv/uv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 45ea95ce79b4..91e088ac6904 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -8,6 +8,7 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; struct cpumask; struct mm_struct; +struct flush_tlb_info; #ifdef CONFIG_X86_UV #include -- 2.21.0
Re: [PATCH v3 1/6] block: revert back to synchronous request_queue removal
On Fri, May 01, 2020 at 05:22:12PM -0700, Bart Van Assche wrote: > > expected behaviour before and it now fails as the device is still present >^ >behavior? That's UK/US spelling. We do not "correct" one to the other. Documentation/doc-guide/contributing.rst: - Both American and British English spellings are allowed within the Documentation/doc-guide/contributing.rst- kernel documentation. There is no need to fix one by replacing it with Documentation/doc-guide/contributing.rst- the other.
Re: [PATCH 3/3] iio: adc: ti_am335x_adc: convert rest of probe to devm_ functions
On Tue, 28 Apr 2020 14:14:30 +0300 Alexandru Ardelean wrote: > This change converts the rest of the probe to use devm_ functions. > Consequently this allows us to remove the remove hook. > > It tries to preserve the initial order or probe & remove. > The devm_add_action() call hooks the cleanup routine (what's needed still > for the remove part). > If that doesn't work the DMA channel is cleaned up manually inside the > probe hook. This done (like this) because the remove hook has a peculiar > cleanup that tries to restore a step-mask, and that only seems to happen on > the remove hook, and not in any probe error-cleanup paths. > > Signed-off-by: Alexandru Ardelean First two patches are fine, but this last one is (as you've noted) more complex. I'd like to cleanup the complexity rather than papering over it. So the real question is why we need to restore the step-mask on exit, but not in other paths in the code. From what I recall (and it's been quite a lot of years) the step mask is controlling the 'scan' so that we capture the set of enabled channels and no others (there is a mux that is being controlled). The current optimization is to not bother resetting that to empty when we read individual channels, or come out of buffered mode because we will set it anyway when moving to some new mode. What I can't understand is why we need to set it in the exit path? This is a complex corner given the involvement of the touchscreen driver and mfd. My first inclination is we may be better off leaving it alone unless we have a test setup to make sure we fully understand what is going on. Given your stated reason for tidying this up was to deal with the buffer stuff and this has no impact on that, I'll take patches 1 and 2 for now and leave this one out. However, I'd like to leave more time for comments on those two as well (though they seem 'obviously' correct to me). Thanks, Jonathan > --- > drivers/iio/adc/ti_am335x_adc.c | 63 + > 1 file changed, 32 insertions(+), 31 deletions(-) > > diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c > index 03b2ab649cc3..9fac83e036c1 100644 > --- a/drivers/iio/adc/ti_am335x_adc.c > +++ b/drivers/iio/adc/ti_am335x_adc.c > @@ -562,6 +562,18 @@ static int tiadc_request_dma(struct platform_device > *pdev, > return -ENOMEM; > } > > +static void tiadc_cleanup_dma(struct tiadc_device *adc_dev) > +{ > + struct tiadc_dma *dma = &adc_dev->dma; > + > + if (!dma->chan) > + return; > + > + dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE, > + dma->buf, dma->addr); > + dma_release_channel(dma->chan); > +} > + > static int tiadc_parse_dt(struct platform_device *pdev, > struct tiadc_device *adc_dev) > { > @@ -593,6 +605,17 @@ static int tiadc_parse_dt(struct platform_device *pdev, > return 0; > } > > +static void tiadc_cleanup(void *data) > +{ > + struct tiadc_device *adc_dev = data; > + u32 step_en; > + > + tiadc_cleanup_dma(adc_dev); > + > + step_en = get_adc_step_mask(adc_dev); > + am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); > +} > + > static int tiadc_probe(struct platform_device *pdev) > { > struct iio_dev *indio_dev; > @@ -635,48 +658,27 @@ static int tiadc_probe(struct platform_device *pdev) > IRQF_SHARED, > &tiadc_buffer_setup_ops); > > + err = devm_iio_device_register(&pdev->dev, indio_dev); > if (err) > - goto err_free_channels; > - > - err = iio_device_register(indio_dev); > - if (err) > - goto err_buffer_unregister; > + return err; > > platform_set_drvdata(pdev, indio_dev); > > err = tiadc_request_dma(pdev, adc_dev); > if (err && err == -EPROBE_DEFER) > - goto err_dma; > + return err; > + > + err = devm_add_action(&pdev->dev, tiadc_cleanup, adc_dev); > + if (err) > + goto err_free_dma; > > return 0; > > -err_dma: > - iio_device_unregister(indio_dev); > -err_buffer_unregister: > -err_free_channels: > +err_free_dma: > + tiadc_cleanup_dma(adc_dev); > return err; > } > > -static int tiadc_remove(struct platform_device *pdev) > -{ > - struct iio_dev *indio_dev = platform_get_drvdata(pdev); > - struct tiadc_device *adc_dev = iio_priv(indio_dev); > - struct tiadc_dma *dma = &adc_dev->dma; > - u32 step_en; > - > - if (dma->chan) { > - dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE, > - dma->buf, dma->addr); > - dma_release_channel(dma->chan); > - } > - iio_device_unregister(indio_dev); > - > - step_en = get_adc_step_mask(adc_dev); > - am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); > - > - return 0; > -} > - > static int __maybe_unused tiadc_suspend(struct device *dev) > { > struct i
RE: [PATCH v4 6/8] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
Hi Avri, On Sun, 2020-05-03 at 08:00 +, Avri Altman wrote: > > > - if (!(hba->dev_info.b_wb_buffer_type && > > - hba->dev_info.d_wb_alloc_units)) > > - goto wb_disabled; > > + if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_SHARED) { > > + hba->dev_info.d_wb_alloc_units = > > + get_unaligned_be32(desc_buf + > > + DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS); > > + if (!hba->dev_info.d_wb_alloc_units) > > + goto wb_disabled; > > + } else { > > + for (lun = 0; lun < hba->dev_info.max_lu_supported; lun++) { > max_lu_supported is determined according to bMaxNumberLU in the geometry > descriptor, > which can be 32. WB buffer however, is only valid only for LU 0, ..., LU7. > Better to add this new limit to ufs.h. Thanks for noticing this. I will fix it in next version. > > > + ret = ufshcd_read_unit_desc_param(hba, > > + lun, > > + UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS, > > + (u8 *)&d_lu_wb_buf_alloc, > > + sizeof(d_lu_wb_buf_alloc)); > > + if (ret) > > + goto wb_disabled; > I think you should just continue here, as it is ok for the query to fail. > The spec says: > The WriteBooster Buffer is available only for the logical units from 0 to 7 > which are configured as > "normal memory type" (bMemoryType = 00h) and "not Boot well known logical > unit" (bBootLunID = > 00h), otherwise the Query Request shall fail and the Query Response field > shall be set to "General > Failure". > > Sorry for not noticing this earlier. Always appreciate your review and always not being too late : ) The spec does not mention clearly that the Query Request shall fail for Read or Write. Although I think it shall fail for Write only, i.e., fail during configuration only, it is better to let fail being skipped and check d_lu_wb_buf_alloc only anyway. I will fix this as well in next version. Thanks, Stanley Chu > > Thanks, > Avri > > + if (d_lu_wb_buf_alloc) { > > + hba->dev_info.wb_dedicated_lu = lun; > > + break; > > + } > > + } > > > > + if (!d_lu_wb_buf_alloc) > > + goto wb_disabled; > > + } > > return; > > > > wb_disabled: > > diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h > > index 898883058e3a..f232a67fd9b3 100644 > > --- a/drivers/scsi/ufs/ufshcd.h > > +++ b/drivers/scsi/ufs/ufshcd.h > > @@ -861,6 +861,13 @@ static inline bool > > ufshcd_keep_autobkops_enabled_except_suspend( > > return hba->caps & > > UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND; > > } > > > > +static inline u8 ufshcd_wb_get_flag_index(struct ufs_hba *hba) > > +{ > > + if (hba->dev_info.b_wb_buffer_type == > > WB_BUF_MODE_LU_DEDICATED) > > + return hba->dev_info.wb_dedicated_lu; > > + return 0; > > +} > > + > > extern int ufshcd_runtime_suspend(struct ufs_hba *hba); > > extern int ufshcd_runtime_resume(struct ufs_hba *hba); > > extern int ufshcd_runtime_idle(struct ufs_hba *hba); > > -- > > 2.18.0 > > ___ > Linux-mediatek mailing list > linux-media...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-mediatek
[PATCH] usb: gadget: audio: Fix a missing error return value in audio_bind()
If 'usb_otg_descriptor_alloc()' fails, we must return an error code, not 0. Fixes: 56023ce0fd70 ("usb: gadget: audio: allocate and init otg descriptor by otg capabilities") Signed-off-by: Christophe JAILLET --- drivers/usb/gadget/legacy/audio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index dd81fd538cb8..a748ed0842e8 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -300,8 +300,10 @@ static int audio_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(cdev->gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto fail; + } usb_otg_descriptor_init(cdev->gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; -- 2.25.1
Re: [PATCH v3 01/11] iio: light: cm32181: Switch to new style i2c-driver probe function
On Tue, 28 Apr 2020 19:29:13 +0200 Hans de Goede wrote: > Switch to the new style i2c-driver probe_new probe function and drop the > unnecessary i2c_device_id table (we do not have any old style board files > using this). > > This is a preparation patch for adding ACPI binding support. > > Signed-off-by: Hans de Goede > --- > Changes in v3: > - This is a new patch in v3 of this patch-set > --- > drivers/iio/light/cm32181.c | 15 +++ > 1 file changed, 3 insertions(+), 12 deletions(-) > > diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c > index 5f4fb5674fa0..cc57190a24cb 100644 > --- a/drivers/iio/light/cm32181.c > +++ b/drivers/iio/light/cm32181.c > @@ -294,8 +294,7 @@ static const struct iio_info cm32181_info = { > .attrs = &cm32181_attribute_group, > }; > > -static int cm32181_probe(struct i2c_client *client, > - const struct i2c_device_id *id) > +static int cm32181_probe(struct i2c_client *client) > { > struct cm32181_chip *cm32181; > struct iio_dev *indio_dev; > @@ -316,7 +315,7 @@ static int cm32181_probe(struct i2c_client *client, > indio_dev->channels = cm32181_channels; > indio_dev->num_channels = ARRAY_SIZE(cm32181_channels); > indio_dev->info = &cm32181_info; > - indio_dev->name = id->name; > + indio_dev->name = dev_name(&client->dev); ABI breakage. The name needs to be unaffected by this patch and I'm fairly sure it just gained the vendor prefix. So to drop that table, you need to provide the 'clean' part number somewhere else. Seeing as driver currently only supports one number, you could just provide it directly here. However, as you are going to add support for another part number later, you'll need to do something more clever when you introduce that. I'll make this suggestion in that patch, but I think you should add a chip_info structure for each of the supported chips rather than using a switch to put a number of different elements in place. The name would then go in there. Jonathan > indio_dev->modes = INDIO_DIRECT_MODE; > > ret = cm32181_reg_init(cm32181); > @@ -338,13 +337,6 @@ static int cm32181_probe(struct i2c_client *client, > return 0; > } > > -static const struct i2c_device_id cm32181_id[] = { > - { "cm32181", 0 }, > - { } > -}; > - > -MODULE_DEVICE_TABLE(i2c, cm32181_id); > - > static const struct of_device_id cm32181_of_match[] = { > { .compatible = "capella,cm32181" }, > { } > @@ -356,8 +348,7 @@ static struct i2c_driver cm32181_driver = { > .name = "cm32181", > .of_match_table = of_match_ptr(cm32181_of_match), > }, > - .id_table = cm32181_id, > - .probe = cm32181_probe, > + .probe_new = cm32181_probe, > }; > > module_i2c_driver(cm32181_driver);
[PATCH v6] gpio: pca953x: Add Maxim MAX7313 PWM support
The MAX7313 chip is fully compatible with the PCA9535 on its basic functions but can also manage the intensity on each of its ports with PWM. Each output is independent and may be tuned with 16 values (4 bits per output). The period is always 32kHz, only the duty-cycle may be changed. One can use any output as GPIO or PWM. Signed-off-by: Miquel Raynal --- Changes in v6: * Rebased on top of v5.7-rc3. * Added a call to max7313_pwm_remove() in pca953x_remove() to eventually run pwmchip_remove(). Changes in v5: * Enhanced the derivation of the intensity from the duty_cycle and the other way around by creating two helpers. These helpers use a more precise fixed point calculation logic than before (multiply then divide instead of the opposite). * The above change also takes into account that the period cannot be changed, so it doest not matter the given period (as long as it is considered as valid), the actual period used for it will be the one of the IP (not the one given by the user). * Simplified #define's as suggested by Andy. * Simplified the check for the IP being compatible with these PWM bits as proposed by Andy, also moved into a helper. * Added missing error checks on regmap_read(). As the main function using it returns void, I decided to print a warning and return a duty_cycle value of 0. * Removed a redundant condition. * Simplified the access to the device structure from the PWM chip structure. * Used __assign_bit() instead of the set_bit()/clear_bit() couple. * I did not split the driver as I think it is too much work for me right now. Changes in v4: * Fix wrong comment about register value. * Rewrite ->set_state() to make it more readable, include the fact that the phase may blink and to limit the number of blink changes when possible ("lazy switching" as discussed with Uwe). * Prevent using managed memory when not relevant. * Add a definition to the master intensity shift. * Rename all struct pwm_device to pwm and all struct pwm_chip as chip. Then, struct pca953x_chip are called pca_chip instead of chip and struct max7313_pwm are called max_pwm intead of pwm. * Enhance the comment about glitch-free hardware. * Add a plain error check at the ->pwm_probe() return location. * Rename duty_cycle to intensity when relevant. * Do not initialize the PWM in ->request(). Also do not change the state in ->free(). * New way to count enabled/disabled PWM (with a bitmap). Disable the oscillator only when 0 PWM are in use, enable it when there is one. Also always set the pin to output state otherwise the default might be input. * Force state->enable to be true and drop all the boilerplate around enable and .duty_cycle. Changes in v3: * Added two error messages in ->request(). * Protected the PWM count agains races with an additional mutex. * Dropped an useless check on the period value in ->apply(). * Forced the .period to be constant. * Checked state->polarity when needed. * Used DIV_ROUND_DOWN_ULL for computing the duty_cycle. * Implemented ->get_state(). * Added a comment to explain that the GPIO functionality is not harmed by the global intensity setting. Changes in v2: * Removed the hardcoding of PWM_CHANNELS, changed the code to use the number of GPIO lines which is programatically known. * Used per pwm_device chip data to store the GPIO descriptors instead of having a static array of GPIO descriptors in the private PWM structure. It also enhanced the readability. * Rename an offset variable: s/off/shift/. * The default PWM state is now static low instead of input. * Used the GPIO as regular consumer thanks to the stored GPIO descriptors to "make it more idiomatic" (requested by Thierry). * Used gpiochip_request_own_desc() instead of gpio_to_desc()/gpiod_request(). This prevented the build issue and an additional dependency that would have requested a DEPENDS ON line in Kconfig. * Enhanced the return line of max7313_pwm_probe(). drivers/gpio/gpio-pca953x.c | 413 +++- 1 file changed, 411 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 5638b4e5355f..ba5e1af0d281 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -12,18 +12,22 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include +#include "gpiolib.h" + #define PCA953X_INPUT 0x00 #define PCA953X_OUTPUT 0x01 #define PCA953X_INVERT 0x02 @@ -63,11 +67,18 @@ #define PCA_INTBIT(8) #define PCA_PCAL BIT(9) +#define MAX_PWMBIT(10) #define PCA_LATCH_INT (PCA_PCAL | PCA_INT) #define PCA953X_TYPE BIT(12) #define PCA957X_TYPE BIT(13) #define PCA_TYPE_MASK GENMASK(15, 12) +#define MAX7313_MASTER 0x0E +#define MAX7313_CONFIGURATI
Re: [PATCH 1/6] iio: chemical: scd30: add core driver
On Sat, May 02, 2020 at 05:37:38PM +0100, Jonathan Cameron wrote: > On Tue, 28 Apr 2020 09:51:01 +0200 > Tomasz Duszynski wrote: > > > On Sat, Apr 25, 2020 at 07:55:34PM +0100, Jonathan Cameron wrote: > > > On Wed, 22 Apr 2020 16:11:30 +0200 > > > Tomasz Duszynski wrote: > > > > > > > Add Sensirion SCD30 carbon dioxide core driver. > > > > > > > > Signed-off-by: Tomasz Duszynski > > > Hi Tomasz > > > > > > As you've probably guessed the big questions are around the custom ABI. > > > > > > Few other things inline. > > > > > > Jonathan > > > > ... > > > > > +static int scd30_read_meas(struct scd30_state *state) > > > > +{ > > > > + int i, ret; > > > > + > > > > + ret = scd30_command(state, CMD_READ_MEAS, 0, (char > > > > *)state->meas, > > > > + sizeof(state->meas)); > > > > + if (ret) > > > > + return ret; > > > > + > > > > + for (i = 0; i < ARRAY_SIZE(state->meas); i++) > > > > + state->meas[i] = scd30_float_to_fp(state->meas[i]); > > > > > > We have previously discussed proving direct floating point channel types > > > for the rare devices that actually provide floating point data in > > > a standard format. > > > > > > I'm happy to revisit that if you would like to. > > > > > > > Thanks for reminding me :). > > > > In that case I admit that some float helper in iio would be a good thing to > > have. Especially that there will be at least 2 sensors using it. > > > > I'd work on that after this driver makes it into the tree. > > > > How does it sound? > > The problem is that, if we do it in that order we have ABI for this > device that we should really maintain. We can probably get away > with changing it on the basis the channel type is self describing anyway > but it's not ideal. > > So probably fine but not best practice... > While I generally agree I can also easily imagine inclusion delay caused by that change. I need to give some more though to this. > > > > > > + > > > > + /* > > > > +* Accuracy within calibrated operating range is > > > > +* +-(30ppm + 3% measurement) so fractional part does > > > > +* not add real value. Moreover, ppm is an integer. > > > > +*/ > > > > + state->meas[CONC] /= 100; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int scd30_wait_meas_irq(struct scd30_state *state) > > > > +{ > > > > + int ret, timeout = msecs_to_jiffies(state->meas_interval * > > > > 1250); > > > > + > > > > + reinit_completion(&state->meas_ready); > > > > + enable_irq(state->irq); > > > > > > So this is just 'grab the next one'? > > > > > > > Yes, grab the fresh one. Moreover enabling interrupts only when necessary > > can > > limit pointless buss traffic. Reason being irq is acknowledged by reading > > data > > from sensor. > > > > As mentioned below, it seems to me that we should really be starting this > device only when we want a reading. Hence any interrupt (subject to possible > races) should be valid. Hence we would not be enabling and disabling the > interrupt controller mask on this line. > While it's okay for triggered mode that isn't so ideal for polled mode because of extra time needed by sensor to actually spin up. You start measuring and expect new data to arrive within 2 seconds (given 0.5Hz sampling frequency is set) but they can actually show up within 8 secs. Not very reliable so to say. Thus I think sticking to continuous sampling is preferred here. > > > > > +static int scd30_setup_trigger(struct iio_dev *indio_dev) > > > > +{ > > > > + struct scd30_state *state = iio_priv(indio_dev); > > > > + struct device *dev = indio_dev->dev.parent; > > > > + struct iio_trigger *trig; > > > > + int ret; > > > > + > > > > + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, > > > > + indio_dev->id); > > > > + if (!trig) { > > > > + dev_err(dev, "failed to allocate trigger\n"); > > > > + return -ENOMEM; > > > > + } > > > > + > > > > + trig->dev.parent = dev; > > > > + trig->ops = &scd30_trigger_ops; > > > > + iio_trigger_set_drvdata(trig, indio_dev); > > > > + > > > > + ret = devm_iio_trigger_register(dev, trig); > > > > + if (ret) > > > > + return ret; > > > > + > > > > + indio_dev->trig = iio_trigger_get(trig); > > > > + > > > > + ret = devm_request_threaded_irq(dev, state->irq, > > > > scd30_irq_handler, > > > > + scd30_irq_thread_handler, > > > > + IRQF_TRIGGER_HIGH | > > > > IRQF_ONESHOT, > > > > + indio_dev->name, indio_dev); > > > > + if (ret) > > > > + dev_err(dev, "failed to request irq\n"); > > > > > > I'm guessing this is a device without any means to disable the interrupt > > > being generated? In w
Re: [PATCH v3 04/11] iio: light: cm32181: Add support for the CM3218
On Tue, 28 Apr 2020 19:29:16 +0200 Hans de Goede wrote: > Add support for the CM3218 which is an older version of the > CM32181. > > This is based on a newer version of cm32181.c, with a copyright of: > > * Copyright (C) 2014 Capella Microsystems Inc. > * Author: Kevin Tsai > * > * This program is free software; you can redistribute it and/or modify it > * under the terms of the GNU General Public License version 2, as published > * by the Free Software Foundation. > > Which is floating around on the net in various places, but the changes > from this newer version never made it upstream. > > This was tested on an Asus T100TA and an Asus T100CHI, which both come > with the CM3218 variant of the light sensor. > > Reviewed-by: Andy Shevchenko > Signed-off-by: Hans de Goede The need to also store the name for the different sensors makes the case for picking between 'chip_info' structures in here stronger. So I'd do that instead of setting multiple elements in your switch statement... (See inline) > --- > drivers/iio/light/cm32181.c | 48 +++-- > 1 file changed, 36 insertions(+), 12 deletions(-) > > diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c > index 6fc0a753c499..065bc7a11f84 100644 > --- a/drivers/iio/light/cm32181.c > +++ b/drivers/iio/light/cm32181.c > @@ -55,15 +55,24 @@ static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = { > CM32181_REG_ADDR_CMD, > }; > > -static const int als_it_bits[] = {12, 8, 0, 1, 2, 3}; > -static const int als_it_value[] = {25000, 5, 10, 20, 40, > - 80}; > +/* CM3218 Family */ > +static const int cm3218_als_it_bits[] = { 0, 1, 2, 3 }; > +static const int cm3218_als_it_values[] = { 10, 20, 40, 80 }; > + > +/* CM32181 Family */ > +static const int cm32181_als_it_bits[] = { 12, 8, 0, 1, 2, 3 }; > +static const int cm32181_als_it_values[] = { > + 25000, 5, 10, 20, 40, 80 > +}; > > struct cm32181_chip { > struct i2c_client *client; > struct mutex lock; > u16 conf_regs[CM32181_CONF_REG_NUM]; > int calibscale; > + int num_als_it; > + const int *als_it_bits; > + const int *als_it_values; These are constant for each type of chip and come as a set. Better to just have a cm32181_chip_info structure with all 3 in it (and the name as mentioned earlier). That way your switch below just becomes a matter of setting a single pointer for each case. > }; > > /** > @@ -85,8 +94,21 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181) > return ret; > > /* check device ID */ > - if ((ret & 0xFF) != 0x81) > + switch (ret & 0xFF) { > + case 0x18: /* CM3218 */ I'd ideally like to see a sanity check that we have the part expected. So the compatible matches what we actually get. If it doesn't but the part is still one we support print a warning. > + cm32181->num_als_it = ARRAY_SIZE(cm3218_als_it_bits); > + cm32181->als_it_bits = cm3218_als_it_bits; > + cm32181->als_it_values = cm3218_als_it_values; > + break; > + case 0x81: /* CM32181 */ > + case 0x82: /* CM32182, fully compat. with CM32181 */ > + cm32181->num_als_it = ARRAY_SIZE(cm32181_als_it_bits); > + cm32181->als_it_bits = cm32181_als_it_bits; > + cm32181->als_it_values = cm32181_als_it_values; > + break; > + default: > return -ENODEV; > + } > > /* Default Values */ > cm32181->conf_regs[CM32181_REG_ADDR_CMD] = > @@ -121,9 +143,9 @@ static int cm32181_read_als_it(struct cm32181_chip > *cm32181, int *val2) > als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD]; > als_it &= CM32181_CMD_ALS_IT_MASK; > als_it >>= CM32181_CMD_ALS_IT_SHIFT; > - for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) { > - if (als_it == als_it_bits[i]) { > - *val2 = als_it_value[i]; > + for (i = 0; i < cm32181->num_als_it; i++) { > + if (als_it == cm32181->als_it_bits[i]) { > + *val2 = cm32181->als_it_values[i]; > return IIO_VAL_INT_PLUS_MICRO; > } > } > @@ -146,14 +168,14 @@ static int cm32181_write_als_it(struct cm32181_chip > *cm32181, int val) > u16 als_it; > int ret, i, n; > > - n = ARRAY_SIZE(als_it_value); > + n = cm32181->num_als_it; > for (i = 0; i < n; i++) > - if (val <= als_it_value[i]) > + if (val <= cm32181->als_it_values[i]) > break; > if (i >= n) > i = n - 1; > > - als_it = als_it_bits[i]; > + als_it = cm32181->als_it_bits[i]; > als_it <<= CM32181_CMD_ALS_IT_SHIFT; > > mutex_lock(&cm32181->lock); > @@ -265,11 +287,12 @@ static int cm32181_write_raw(struct iio_dev *indio_dev, > static ssize_t cm32181_get_it_available(struct device *dev, >
Re: [PATCH v3 05/11] iio: light: cm32181: Clean up the probe function a bit
On Tue, 28 Apr 2020 19:29:17 +0200 Hans de Goede wrote: > 3 small cleanups to cm32181_probe(): > > 1. Do not log an error when we fail to allocate memory (as a general > rule drivers do not log errors for this as the kernel will already > have complained loudly that it could not alloc the mem). > > 2. Remove the i2c_set_clientdata() call, we never use i2c_get_clientdata() > or dev_get_drvdata() anywhere. > > 3. Add a dev helper variable and use it in various places instead of > &client->dev. > > Signed-off-by: Hans de Goede looks fine to me. J > --- > Changes in v3: > - This is a new patch in v3 of this patch-set > --- > drivers/iio/light/cm32181.c | 22 -- > 1 file changed, 8 insertions(+), 14 deletions(-) > > diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c > index 065bc7a11f84..8fe49610fc26 100644 > --- a/drivers/iio/light/cm32181.c > +++ b/drivers/iio/light/cm32181.c > @@ -326,41 +326,35 @@ static const struct iio_info cm32181_info = { > > static int cm32181_probe(struct i2c_client *client) > { > + struct device *dev = &client->dev; > struct cm32181_chip *cm32181; > struct iio_dev *indio_dev; > int ret; > > - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181)); > - if (!indio_dev) { > - dev_err(&client->dev, "devm_iio_device_alloc failed\n"); > + indio_dev = devm_iio_device_alloc(dev, sizeof(*cm32181)); > + if (!indio_dev) > return -ENOMEM; > - } > > cm32181 = iio_priv(indio_dev); > - i2c_set_clientdata(client, indio_dev); > cm32181->client = client; > > mutex_init(&cm32181->lock); > - indio_dev->dev.parent = &client->dev; > + indio_dev->dev.parent = dev; > indio_dev->channels = cm32181_channels; > indio_dev->num_channels = ARRAY_SIZE(cm32181_channels); > indio_dev->info = &cm32181_info; > - indio_dev->name = dev_name(&client->dev); > + indio_dev->name = dev_name(dev); > indio_dev->modes = INDIO_DIRECT_MODE; > > ret = cm32181_reg_init(cm32181); > if (ret) { > - dev_err(&client->dev, > - "%s: register init failed\n", > - __func__); > + dev_err(dev, "%s: register init failed\n", __func__); > return ret; > } > > - ret = devm_iio_device_register(&client->dev, indio_dev); > + ret = devm_iio_device_register(dev, indio_dev); > if (ret) { > - dev_err(&client->dev, > - "%s: regist device failed\n", > - __func__); > + dev_err(dev, "%s: regist device failed\n", __func__); > return ret; > } >
Re: [PATCH v3 06/11] iio: light: cm32181: Handle CM3218 ACPI devices with 2 I2C resources
On Tue, 28 Apr 2020 19:29:18 +0200 Hans de Goede wrote: > Some ACPI systems list 2 I2C resources for the CM3218 sensor. On these > systems the first I2cSerialBus ACPI-resource points to the SMBus Alert > Response Address (ARA, 0x0c) and the second I2cSerialBus ACPI-resource > points to the actual CM3218 sensor address: > > Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings > { > Name (SBUF, ResourceTemplate () > { I have a vague recollection that we had case of this where they could come in either order. Could that happen here? My mind may be playing tricks on me of course and that may never happen... Did I ever mention how much the lack of spec for some of these corner cases annoys me? J > I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80, > AddressingMode7Bit, "\\_SB.I2C3", > 0x00, ResourceConsumer, , Exclusive, > ) > I2cSerialBusV2 (0x0048, ControllerInitiated, 0x00061A80, > AddressingMode7Bit, "\\_SB.I2C3", > 0x00, ResourceConsumer, , Exclusive, > ) > Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, ) > { > 0x0033, > } > }) > Return (SBUF) /* \_SB_.I2C3.ALSD._CRS.SBUF */ > } > > Detect this and take the following step to deal with it: > > 1. When a SMBus Alert capable sensor has an Alert asserted, it will >not respond on its actual I2C address. Read a byte from the ARA >to clear any pending Alerts. > > 2. Create a "dummy" client for the actual I2C address and >use that client to communicate with the sensor. > > Signed-off-by: Hans de Goede > --- > Changes in v3: > - Create and use a dummy client instead of relying on i2c-multi-instantiate > to create 2 separate clients for the 2 I2C resources > > Changes in v2 > - s/i2c_client-s/I2C clients/ in added comment > --- > drivers/iio/light/cm32181.c | 22 ++ > 1 file changed, 22 insertions(+) > > diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c > index 8fe49610fc26..c23a5c3a86a3 100644 > --- a/drivers/iio/light/cm32181.c > +++ b/drivers/iio/light/cm32181.c > @@ -51,6 +51,8 @@ > #define CM32181_CALIBSCALE_RESOLUTION1000 > #define MLUX_PER_LUX 1000 > > +#define SMBUS_ALERT_RESPONSE_ADDRESS 0x0c > + > static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = { > CM32181_REG_ADDR_CMD, > }; > @@ -335,6 +337,26 @@ static int cm32181_probe(struct i2c_client *client) > if (!indio_dev) > return -ENOMEM; > > + /* > + * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the > + * SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address. > + * Detect this and take the following step to deal with it: > + * 1. When a SMBus Alert capable sensor has an Alert asserted, it will > + *not respond on its actual I2C address. Read a byte from the ARA > + *to clear any pending Alerts. > + * 2. Create a "dummy" client for the actual I2C address and > + *use that client to communicate with the sensor. > + */ > + if (ACPI_HANDLE(dev) && client->addr == SMBUS_ALERT_RESPONSE_ADDRESS) { > + struct i2c_board_info board_info = { .type = "dummy" }; > + > + i2c_smbus_read_byte(client); > + > + client = i2c_acpi_new_device(dev, 1, &board_info); > + if (IS_ERR(client)) > + return PTR_ERR(client); > + } > + > cm32181 = iio_priv(indio_dev); > cm32181->client = client; >
Re: [PATCH v3 10/11] iio: light: cm32181: Add support for parsing CPM0 and CPM1 ACPI tables
On Tue, 28 Apr 2020 19:29:22 +0200 Hans de Goede wrote: > On ACPI based systems the CPLM3218 ACPI device node describing the > CM3218[1] sensor typically will have some extra tables with register > init values for initializing the sensor and calibration info. > > This is based on a newer version of cm32181.c, with a copyright of: > > * Copyright (C) 2014 Capella Microsystems Inc. > * Author: Kevin Tsai > * > * This program is free software; you can redistribute it and/or modify it > * under the terms of the GNU General Public License version 2, as published > * by the Free Software Foundation. > > Which is floating around on the net in various places, but the changes > from this newer version never made it upstream. > > This was tested on the following models: Acer Switch 10 SW5-012 (CM32181) > Asus T100TA (CM3218), Asus T100CHI (CM3218) and HP X2 10-n000nd (CM32181). I assume it's far too much to hope this CPM0 / CPM1 stuff is actually defined in a spec anywhere? There are standard way of adding vendor specific data blobs to ACPI and this isn't one of them (unless I'm missing something). People need to beat up vendors earlier about this stuff. Grumble over... Code looks fine to me, but I'd like an ACPI review ideally. Thanks, Jonathan > > Reviewed-by: Andy Shevchenko > Signed-off-by: Hans de Goede > --- > Changes in v2: > - Factor out the parsing into a separate helper function > --- > drivers/iio/light/cm32181.c | 101 > 1 file changed, 101 insertions(+) > > diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c > index cae2264e4336..d8b128286527 100644 > --- a/drivers/iio/light/cm32181.c > +++ b/drivers/iio/light/cm32181.c > @@ -4,6 +4,7 @@ > * Author: Kevin Tsai > */ > > +#include > #include > #include > #include > @@ -53,6 +54,15 @@ > > #define SMBUS_ALERT_RESPONSE_ADDRESS 0x0c > > +/* CPM0 Index 0: device-id (3218 or 32181), 1: Unknown, 2: init_regs_bitmap > */ > +#define CPM0_REGS_BITMAP 2 > +#define CPM0_HEADER_SIZE 3 > + > +/* CPM1 Index 0: lux_per_bit, 1: calibscale, 2: resolution (10) */ > +#define CPM1_LUX_PER_BIT 0 > +#define CPM1_CALIBSCALE 1 > +#define CPM1_SIZE3 > + > /* CM3218 Family */ > static const int cm3218_als_it_bits[] = { 0, 1, 2, 3 }; > static const int cm3218_als_it_values[] = { 10, 20, 40, 80 }; > @@ -65,6 +75,7 @@ static const int cm32181_als_it_values[] = { > > struct cm32181_chip { > struct i2c_client *client; > + struct device *dev; > struct mutex lock; > u16 conf_regs[CM32181_CONF_REG_NUM]; > unsigned long init_regs_bitmap; > @@ -76,6 +87,92 @@ struct cm32181_chip { > const int *als_it_values; > }; > > +static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2); > + > +#ifdef CONFIG_ACPI > +/** > + * cm32181_acpi_get_cpm() - Get CPM object from ACPI > + * @client pointer of struct i2c_client. > + * @obj_name pointer of ACPI object name. > + * @countmaximum size of return array. > + * @vals pointer of array for return elements. > + * > + * Convert ACPI CPM table to array. > + * > + * Return: -ENODEV for fail. Otherwise is number of elements. > + */ > +static int cm32181_acpi_get_cpm(struct device *dev, char *obj_name, > + u64 *values, int count) > +{ > + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; > + union acpi_object *cpm, *elem; > + acpi_handle handle; > + acpi_status status; > + int i; > + > + handle = ACPI_HANDLE(dev); > + if (!handle) > + return -ENODEV; > + > + status = acpi_evaluate_object(handle, obj_name, NULL, &buffer); > + if (ACPI_FAILURE(status)) { > + dev_err(dev, "object %s not found\n", obj_name); > + return -ENODEV; > + } > + > + cpm = buffer.pointer; > + if (cpm->package.count > count) > + dev_warn(dev, "%s table contains %d values, only using first %d > values\n", > + obj_name, cpm->package.count, count); > + > + count = min_t(int, cpm->package.count, count); > + for (i = 0; i < count; i++) { > + elem = &(cpm->package.elements[i]); > + values[i] = elem->integer.value; > + } > + > + kfree(buffer.pointer); > + > + return count; > +} > + > +static void cm32181_acpi_parse_cpm_tables(struct cm32181_chip *cm32181) > +{ > + u64 vals[CPM0_HEADER_SIZE + CM32181_CONF_REG_NUM]; > + struct device *dev = cm32181->dev; > + int i, count; > + > + count = cm32181_acpi_get_cpm(dev, "CPM0", vals, ARRAY_SIZE(vals)); > + if (count <= CPM0_HEADER_SIZE) > + return; > + > + count -= CPM0_HEADER_SIZE; > + > + cm32181->init_regs_bitmap = vals[CPM0_REGS_BITMAP]; > + cm32181->init_regs_bitmap &= GENMASK(count - 1, 0); > + for_each_set_bit(i, &cm32181->init_regs_bitmap, coun
[tip: x86/urgent] x86/unwind/orc: Move ORC sorting variables under !CONFIG_MODULES
The following commit has been merged into the x86/urgent branch of tip: Commit-ID: fb9cbbc895eb6e986dc90c928a35c793d75f435a Gitweb: https://git.kernel.org/tip/fb9cbbc895eb6e986dc90c928a35c793d75f435a Author:Josh Poimboeuf AuthorDate:Tue, 28 Apr 2020 02:16:40 -05:00 Committer: Ingo Molnar CommitterDate: Sun, 03 May 2020 13:23:28 +02:00 x86/unwind/orc: Move ORC sorting variables under !CONFIG_MODULES Fix the following warnings seen with !CONFIG_MODULES: arch/x86/kernel/unwind_orc.c:29:26: warning: 'cur_orc_table' defined but not used [-Wunused-variable] 29 | static struct orc_entry *cur_orc_table = __start_orc_unwind; | ^ arch/x86/kernel/unwind_orc.c:28:13: warning: 'cur_orc_ip_table' defined but not used [-Wunused-variable] 28 | static int *cur_orc_ip_table = __start_orc_unwind_ip; | ^~~~ Fixes: 153eb2223c79 ("x86/unwind/orc: Convert global variables to static") Reported-by: Stephen Rothwell Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: H. Peter Anvin Cc: Linux Next Mailing List Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lore.kernel.org/r/20200428071640.psn5m7eh3zt2in4v@treble --- arch/x86/kernel/unwind_orc.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 0ebc11a..5b0bd85 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -24,10 +24,6 @@ extern struct orc_entry __stop_orc_unwind[]; static bool orc_init __ro_after_init; static unsigned int lookup_num_blocks __ro_after_init; -static DEFINE_MUTEX(sort_mutex); -static int *cur_orc_ip_table = __start_orc_unwind_ip; -static struct orc_entry *cur_orc_table = __start_orc_unwind; - static inline unsigned long orc_ip(const int *ip) { return (unsigned long)ip + *ip; @@ -192,6 +188,10 @@ static struct orc_entry *orc_find(unsigned long ip) #ifdef CONFIG_MODULES +static DEFINE_MUTEX(sort_mutex); +static int *cur_orc_ip_table = __start_orc_unwind_ip; +static struct orc_entry *cur_orc_table = __start_orc_unwind; + static void orc_sort_swap(void *_a, void *_b, int size) { struct orc_entry *orc_a, *orc_b;
Re: [PATCH] nfp: abm: fix a memory leak bug
… > Fix this issue by adding nfp_nsp_close(nsp) in the error path. How do you think about a wording variant like the following? Subject: [PATCH v2] nfp: abm: Fix incomplete release of system resources in nfp_abm_vnic_set_mac() Change description: … Thus add a call of the function “nfp_nsp_close” for the completion of the exception handling. … > +++ b/drivers/net/ethernet/netronome/nfp/abm/main.c > @@ -283,6 +283,7 @@ nfp_abm_vnic_set_mac(struct nfp_pf *pf, struct nfp_abm > *abm, struct nfp_net *nn, > if (!nfp_nsp_has_hwinfo_lookup(nsp)) { > nfp_warn(pf->cpp, "NSP doesn't support PF MAC generation\n"); > eth_hw_addr_random(nn->dp.netdev); > + nfp_nsp_close(nsp); > return; > } I suggest to reconsider the order for resource clean-up function calls a bit more. + nfp_nsp_close(nsp); - eth_hw_addr_random(nn->dp.netdev); - return; + goto generate_random_address; Should such a jump target be added in another update step? Would you like to add the tag “Fixes”? Regards, Markus
[PATCH v5 3/8] scsi: ufs: export ufs_fixup_device_setup() function
Export ufs_fixup_device_setup() to allow vendors to re-use it for fixing device quriks on specified UFS hosts. Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufshcd.c | 7 --- drivers/scsi/ufs/ufshcd.h | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index da7b375709b6..6d5b49c07a69 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6838,12 +6838,12 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) hba->caps &= ~UFSHCD_CAP_WB_EN; } -static void ufs_fixup_device_setup(struct ufs_hba *hba) +void ufshcd_fixup_device_setup(struct ufs_hba *hba, struct ufs_dev_fix *fixups) { struct ufs_dev_fix *f; struct ufs_dev_info *dev_info = &hba->dev_info; - for (f = ufs_fixups; f->quirk; f++) { + for (f = fixups; f->quirk; f++) { if ((f->wmanufacturerid == dev_info->wmanufacturerid || f->wmanufacturerid == UFS_ANY_VENDOR) && ((dev_info->model && @@ -6852,6 +6852,7 @@ static void ufs_fixup_device_setup(struct ufs_hba *hba) hba->dev_quirks |= f->quirk; } } +EXPORT_SYMBOL_GPL(ufshcd_fixup_device_setup); static int ufs_get_device_desc(struct ufs_hba *hba) { @@ -6898,7 +6899,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba) goto out; } - ufs_fixup_device_setup(hba); + ufshcd_fixup_device_setup(hba, ufs_fixups); ufshcd_vops_fixup_dev_quirks(hba); /* diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 5fa03e0f3bd1..f34601121880 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -69,6 +69,7 @@ #include #include "ufs.h" +#include "ufs_quirks.h" #include "ufshci.h" #define UFSHCD "ufshcd" @@ -951,7 +952,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, void ufshcd_auto_hibern8_enable(struct ufs_hba *hba); void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit); - +void ufshcd_fixup_device_setup(struct ufs_hba *hba, + struct ufs_dev_fix *fixups); #define SD_ASCII_STD true #define SD_RAW false int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, -- 2.18.0
[PATCH v5 6/8] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
According to UFS specification, there are two WriteBooster mode of operations: "LU dedicated buffer" mode and "shared buffer" mode. In the "LU dedicated buffer" mode, the WriteBooster Buffer is dedicated to a logical unit. If the device supports the "LU dedicated buffer" mode, this mode is configured by setting bWriteBoosterBufferType to 00h. The logical unit WriteBooster Buffer size is configured by setting the dLUNumWriteBoosterBufferAllocUnits field of the related Unit Descriptor. Only a value greater than zero enables the WriteBooster feature in the logical unit. Modify ufshcd_wb_probe() as above description to support LU Dedicated buffer mode. Note that according to UFS 3.1 specification, the valid value of bDeviceMaxWriteBoosterLUs parameter in Geometry Descriptor is 1, which means at most one LUN can have WriteBooster buffer in "LU dedicated buffer mode". Therefore this patch supports only one LUN with WriteBooster enabled. All WriteBooster related sysfs nodes are specifically mapped to the LUN with WriteBooster enabled in LU Dedicated buffer mode. Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufs-sysfs.c | 11 +++- drivers/scsi/ufs/ufs.h | 10 +++ drivers/scsi/ufs/ufshcd.c| 51 drivers/scsi/ufs/ufshcd.h| 7 + 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index b86b6a40d7e6..a0b3763e1dc2 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -622,16 +622,25 @@ static const struct attribute_group ufs_sysfs_string_descriptors_group = { .attrs = ufs_sysfs_string_descriptors, }; +static inline bool ufshcd_is_wb_flags(enum flag_idn idn) +{ + return ((idn >= QUERY_FLAG_IDN_WB_EN) && + (idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8)); +} + #define UFS_FLAG(_name, _uname) \ static ssize_t _name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ bool flag; \ + u8 index = 0; \ int ret;\ struct ufs_hba *hba = dev_get_drvdata(dev); \ + if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname)) \ + index = ufshcd_wb_get_flag_index(hba); \ pm_runtime_get_sync(hba->dev); \ ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \ - QUERY_FLAG_IDN##_uname, 0, &flag); \ + QUERY_FLAG_IDN##_uname, index, &flag); \ pm_runtime_put_sync(hba->dev); \ if (ret)\ return -EINVAL; \ diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index daac5053b850..b3135344ab3f 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -64,6 +64,9 @@ #define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID) #define UFS_UPIU_WLUN_ID (1 << 7) +/* WriteBooster buffer is available only for the logical unit from 0 to 7 */ +#define UFS_UPIU_MAX_WB_LUN_ID 8 + /* Well known logical unit id in LUN field of UPIU */ enum { UFS_UPIU_REPORT_LUNS_WLUN = 0x81, @@ -330,6 +333,12 @@ enum health_desc_param { HEALTH_DESC_PARAM_LIFE_TIME_EST_B = 0x4, }; +/* WriteBooster buffer mode */ +enum { + WB_BUF_MODE_LU_DEDICATED= 0x0, + WB_BUF_MODE_SHARED = 0x1, +}; + /* * Logical Unit Write Protect * 00h: LU not write protected @@ -559,6 +568,7 @@ struct ufs_dev_info { bool is_lu_power_on_wp; /* Maximum number of general LU supported by the UFS device */ u8 max_lu_supported; + u8 wb_dedicated_lu; u16 wmanufacturerid; /*UFS device Product Name */ u8 *model; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d4a9c479294c..49391bc1ef21 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5205,6 +5205,7 @@ static bool ufshcd_wb_sup(struct ufs_hba *hba) static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable) { int ret; + u8 index; enum query_opcode opcode; if (!ufshcd_wb_sup(hba)) @@ -5217,8 +5218,9 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable) else opcode = UPIU_QUERY_OPCODE_CLEAR_FLAG; + index = ufshcd_wb_get_flag_index(hba); ret = ufshcd_query_flag_retry(hba, opcode, - QUERY_FLAG_IDN_WB_EN,
[PATCH v5 7/8] scsi: ufs-mediatek: enable WriteBooster capability
Enable WriteBooster capability on MediaTek UFS platforms. Signed-off-by: Stanley Chu Reviewed-by: Bean Huo --- drivers/scsi/ufs/ufs-mediatek.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index ce7ba529e613..d503a9d82854 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -269,6 +269,9 @@ static int ufs_mtk_init(struct ufs_hba *hba) /* Enable clock-gating */ hba->caps |= UFSHCD_CAP_CLK_GATING; + /* Enable WriteBooster */ + hba->caps |= UFSHCD_CAP_WB_EN; + /* * ufshcd_vops_init() is invoked after * ufshcd_setup_clock(true) in ufshcd_hba_init() thus -- 2.18.0
[PATCH v5 2/8] scsi: ufs: introduce fixup_dev_quirks vops
Some UFS deivces may have required device quirks or have non-standard features which are enabled only on specified UFS hosts or for special customers. To not "pollute" common device quirk list, i.e., ufs_fixups table for those devices mentioned above, introduce "fixup_dev_quirks" vops to allow vendors to fix or modify device quirks accordingly. Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufshcd.c | 1 + drivers/scsi/ufs/ufshcd.h | 7 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 04ddfb15e858..da7b375709b6 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6899,6 +6899,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba) } ufs_fixup_device_setup(hba); + ufshcd_vops_fixup_dev_quirks(hba); /* * Probe WB only for UFS-3.1 devices or UFS devices with quirk diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 056537e52c19..5fa03e0f3bd1 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -336,6 +336,7 @@ struct ufs_hba_variant_ops { void(*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme, enum ufs_notify_change_status); int (*apply_dev_quirks)(struct ufs_hba *hba); + void(*fixup_dev_quirks)(struct ufs_hba *hba); int (*suspend)(struct ufs_hba *, enum ufs_pm_op); int (*resume)(struct ufs_hba *, enum ufs_pm_op); void(*dbg_register_dump)(struct ufs_hba *hba); @@ -1085,6 +1086,12 @@ static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba) return 0; } +static inline void ufshcd_vops_fixup_dev_quirks(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->fixup_dev_quirks) + hba->vops->fixup_dev_quirks(hba); +} + static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) { if (hba->vops && hba->vops->suspend) -- 2.18.0
[PATCH v5 8/8] scsi: ufs: cleanup WriteBooster feature
Small cleanup as below items, 1. Use ufshcd_is_wb_allowed() directly instead of ufshcd_wb_sup() since ufshcd_wb_sup() just returns the result of ufshcd_is_wb_allowed(). 2. In ufshcd_suspend(), "else if (!ufshcd_is_runtime_pm(pm_op)) can be simplified to "else" since both have the same meaning. This patch does not change any functionality. Signed-off-by: Stanley Chu Reviewed-by: Avri Altman --- drivers/scsi/ufs/ufshcd.c | 20 +++- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 49391bc1ef21..6425b7afd890 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -253,7 +253,6 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up); static irqreturn_t ufshcd_intr(int irq, void *__hba); static int ufshcd_change_power_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *pwr_mode); -static bool ufshcd_wb_sup(struct ufs_hba *hba); static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba); static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba); static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable); @@ -285,7 +284,7 @@ static inline void ufshcd_wb_config(struct ufs_hba *hba) { int ret; - if (!ufshcd_wb_sup(hba)) + if (!ufshcd_is_wb_allowed(hba)) return; ret = ufshcd_wb_ctrl(hba, true); @@ -5197,18 +5196,13 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba) __func__, err); } -static bool ufshcd_wb_sup(struct ufs_hba *hba) -{ - return ufshcd_is_wb_allowed(hba); -} - static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable) { int ret; u8 index; enum query_opcode opcode; - if (!ufshcd_wb_sup(hba)) + if (!ufshcd_is_wb_allowed(hba)) return 0; if (!(enable ^ hba->wb_enabled)) @@ -5264,7 +5258,7 @@ static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba) int ret; u8 index; - if (!ufshcd_wb_sup(hba) || hba->wb_buf_flush_enabled) + if (!ufshcd_is_wb_allowed(hba) || hba->wb_buf_flush_enabled) return 0; index = ufshcd_wb_get_flag_index(hba); @@ -5286,7 +5280,7 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba) int ret; u8 index; - if (!ufshcd_wb_sup(hba) || !hba->wb_buf_flush_enabled) + if (!ufshcd_is_wb_allowed(hba) || !hba->wb_buf_flush_enabled) return 0; index = ufshcd_wb_get_flag_index(hba); @@ -5336,7 +5330,7 @@ static bool ufshcd_wb_keep_vcc_on(struct ufs_hba *hba) int ret; u32 avail_buf; - if (!ufshcd_wb_sup(hba)) + if (!ufshcd_is_wb_allowed(hba)) return false; /* * The ufs device needs the vcc to be ON to flush. @@ -8225,12 +8219,12 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) * configured WB type is 70% full, keep vcc ON * for the device to flush the wb buffer */ - if ((hba->auto_bkops_enabled && ufshcd_wb_sup(hba)) || + if ((hba->auto_bkops_enabled && ufshcd_is_wb_allowed(hba)) || ufshcd_wb_keep_vcc_on(hba)) hba->dev_info.keep_vcc_on = true; else hba->dev_info.keep_vcc_on = false; - } else if (!ufshcd_is_runtime_pm(pm_op)) { + } else { hba->dev_info.keep_vcc_on = false; } -- 2.18.0
[PATCH v5 5/8] scsi: ufs: add "index" in parameter list of ufshcd_query_flag()
For preparation of LU Dedicated buffer mode support on WriteBooster feature, "index" parameter shall be added and allowed to be specified by callers. Signed-off-by: Stanley Chu Reviewed-by: Bean Huo Reviewed-by: Avri Altman Reviewed-by: Can Guo --- drivers/scsi/ufs/ufs-sysfs.c | 2 +- drivers/scsi/ufs/ufshcd.c| 28 +++- drivers/scsi/ufs/ufshcd.h| 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 93484408bc40..b86b6a40d7e6 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -631,7 +631,7 @@ static ssize_t _name##_show(struct device *dev, \ struct ufs_hba *hba = dev_get_drvdata(dev); \ pm_runtime_get_sync(hba->dev); \ ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \ - QUERY_FLAG_IDN##_uname, &flag); \ + QUERY_FLAG_IDN##_uname, 0, &flag); \ pm_runtime_put_sync(hba->dev); \ if (ret)\ return -EINVAL; \ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6d5b49c07a69..d4a9c479294c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2782,13 +2782,13 @@ static inline void ufshcd_init_query(struct ufs_hba *hba, } static int ufshcd_query_flag_retry(struct ufs_hba *hba, - enum query_opcode opcode, enum flag_idn idn, bool *flag_res) + enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res) { int ret; int retries; for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) { - ret = ufshcd_query_flag(hba, opcode, idn, flag_res); + ret = ufshcd_query_flag(hba, opcode, idn, index, flag_res); if (ret) dev_dbg(hba->dev, "%s: failed with error %d, retries %d\n", @@ -2809,16 +2809,17 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, * @hba: per-adapter instance * @opcode: flag query to perform * @idn: flag idn to access + * @index: flag index to access * @flag_res: the flag value after the query request completes * * Returns 0 for success, non-zero in case of failure */ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, - enum flag_idn idn, bool *flag_res) + enum flag_idn idn, u8 index, bool *flag_res) { struct ufs_query_req *request = NULL; struct ufs_query_res *response = NULL; - int err, index = 0, selector = 0; + int err, selector = 0; int timeout = QUERY_REQ_TIMEOUT; BUG_ON(!hba); @@ -4175,7 +4176,7 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba) bool flag_res = true; err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG, - QUERY_FLAG_IDN_FDEVICEINIT, NULL); + QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL); if (err) { dev_err(hba->dev, "%s setting fDeviceInit flag failed with error %d\n", @@ -4186,7 +4187,7 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba) /* poll for max. 1000 iterations for fDeviceInit flag to clear */ for (i = 0; i < 1000 && !err && flag_res; i++) err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, - QUERY_FLAG_IDN_FDEVICEINIT, &flag_res); + QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res); if (err) dev_err(hba->dev, @@ -5001,7 +5002,7 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba) goto out; err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG, - QUERY_FLAG_IDN_BKOPS_EN, NULL); + QUERY_FLAG_IDN_BKOPS_EN, 0, NULL); if (err) { dev_err(hba->dev, "%s: failed to enable bkops %d\n", __func__, err); @@ -5051,7 +5052,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba) } err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG, - QUERY_FLAG_IDN_BKOPS_EN, NULL); + QUERY_FLAG_IDN_BKOPS_EN, 0, NULL); if (err) { dev_err(hba->dev, "%s: failed to disable bkops %d\n", __func__, err); @@ -5217,7 +5218,7 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable) opcode = UPIU_QUERY_OPCODE_CLEAR_FLAG; ret = ufshcd_query_flag_retry(hba, opcode, - QUERY_FLAG_IDN_WB_EN, NULL); + QUERY_FLAG_IDN_WB
[PATCH v5 1/8] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices
WriteBooster feature can be supported by some pre-3.1 UFS devices by upgrading firmware. To enable WriteBooster feature in such devices, introduce a device quirk to relax the entrance condition of ufshcd_wb_probe() to allow host driver to check those devices' WriteBooster capability. WriteBooster feature can be available if below all conditions are satisfied, 1. Host enables WriteBooster capability 2. UFS 3.1 device or UFS pre-3.1 device with quirk UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES enabled 3. Device descriptor has dExtendedUFSFeaturesSupport field 4. WriteBooster support is specified in above field Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufs_quirks.h | 7 drivers/scsi/ufs/ufshcd.c | 67 ++- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index df7a1e6805a3..e3175a63c676 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -101,4 +101,11 @@ struct ufs_dev_fix { */ #define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME (1 << 9) +/* + * Some pre-3.1 UFS devices can support extended features by upgrading + * the firmware. Enable this quirk to make UFS core driver probe and enable + * supported features on such devices. + */ +#define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10) + #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 915e963398c4..04ddfb15e858 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6800,9 +6800,19 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) { + if (!ufshcd_is_wb_allowed(hba)) + return; + + if (hba->desc_size.dev_desc <= DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP) + goto wb_disabled; + hba->dev_info.d_ext_ufs_feature_sup = get_unaligned_be32(desc_buf + DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP); + + if (!(hba->dev_info.d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP)) + goto wb_disabled; + /* * WB may be supported but not configured while provisioning. * The spec says, in dedicated wb buffer mode, @@ -6818,11 +6828,29 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) hba->dev_info.b_presrv_uspc_en = desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN]; - if (!((hba->dev_info.d_ext_ufs_feature_sup & -UFS_DEV_WRITE_BOOSTER_SUP) && - hba->dev_info.b_wb_buffer_type && + if (!(hba->dev_info.b_wb_buffer_type && hba->dev_info.d_wb_alloc_units)) - hba->caps &= ~UFSHCD_CAP_WB_EN; + goto wb_disabled; + + return; + +wb_disabled: + hba->caps &= ~UFSHCD_CAP_WB_EN; +} + +static void ufs_fixup_device_setup(struct ufs_hba *hba) +{ + struct ufs_dev_fix *f; + struct ufs_dev_info *dev_info = &hba->dev_info; + + for (f = ufs_fixups; f->quirk; f++) { + if ((f->wmanufacturerid == dev_info->wmanufacturerid || +f->wmanufacturerid == UFS_ANY_VENDOR) && +((dev_info->model && + STR_PRFX_EQUAL(f->model, dev_info->model)) || + !strcmp(f->model, UFS_ANY_MODEL))) + hba->dev_quirks |= f->quirk; + } } static int ufs_get_device_desc(struct ufs_hba *hba) @@ -6862,10 +6890,6 @@ static int ufs_get_device_desc(struct ufs_hba *hba) model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; - /* Enable WB only for UFS-3.1 */ - if (dev_info->wspecversion >= 0x310) - ufshcd_wb_probe(hba, desc_buf); - err = ufshcd_read_string_desc(hba, model_index, &dev_info->model, SD_ASCII_STD); if (err < 0) { @@ -6874,6 +6898,16 @@ static int ufs_get_device_desc(struct ufs_hba *hba) goto out; } + ufs_fixup_device_setup(hba); + + /* +* Probe WB only for UFS-3.1 devices or UFS devices with quirk +* UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES enabled +*/ + if (dev_info->wspecversion >= 0x310 || + (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES)) + ufshcd_wb_probe(hba, desc_buf); + /* * ufshcd_read_string_desc returns size of the string * reset the error value @@ -6893,21 +6927,6 @@ static void ufs_put_device_desc(struct ufs_hba *hba) dev_info->model = NULL; } -static void ufs_fixup_device_setup(struct ufs_hba *hba) -{ - struct ufs_dev_fix *f; - struct ufs_dev_info *dev_info = &hba->dev_info; - - for (f = ufs_fixups; f->quirk; f++) { - if ((f->wmanufacturerid == dev_info->wmanufacturerid || -f->wmanufacturerid == UFS_ANY_VENDOR
[PATCH v5 4/8] scsi: ufs-mediatek: add fixup_dev_quirks vops
Add fixup_dev_quirk vops in MediaTek UFS platforms and provide an initial vendor-specific device quirk table. Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufs-mediatek.c | 22 +++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 673c16596fb2..ce7ba529e613 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -30,6 +30,12 @@ #define ufs_mtk_device_reset_ctrl(high, res) \ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res) +static struct ufs_dev_fix ufs_mtk_dev_fixups[] = { + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR", + UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES), + END_FIX +}; + static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) { u32 tmp; @@ -555,10 +561,8 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) struct ufs_dev_info *dev_info = &hba->dev_info; u16 mid = dev_info->wmanufacturerid; - if (mid == UFS_VENDOR_SAMSUNG) { - hba->dev_quirks &= ~UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE; + if (mid == UFS_VENDOR_SAMSUNG) ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); - } /* * Decide waiting time before gating reference clock and @@ -575,6 +579,17 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) return 0; } +void ufs_mtk_fixup_dev_quirks(struct ufs_hba *hba) +{ + struct ufs_dev_info *dev_info = &hba->dev_info; + u16 mid = dev_info->wmanufacturerid; + + ufshcd_fixup_device_setup(hba, ufs_mtk_dev_fixups); + + if (mid == UFS_VENDOR_SAMSUNG) + hba->dev_quirks &= ~UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE; +} + /** * struct ufs_hba_mtk_vops - UFS MTK specific variant operations * @@ -589,6 +604,7 @@ static struct ufs_hba_variant_ops ufs_hba_mtk_vops = { .link_startup_notify = ufs_mtk_link_startup_notify, .pwr_change_notify = ufs_mtk_pwr_change_notify, .apply_dev_quirks= ufs_mtk_apply_dev_quirks, + .fixup_dev_quirks= ufs_mtk_fixup_dev_quirks, .suspend = ufs_mtk_suspend, .resume = ufs_mtk_resume, .dbg_register_dump = ufs_mtk_dbg_register_dump, -- 2.18.0
[PATCH v5 0/8] scsi: ufs: support LU Dedicated buffer mode for WriteBooster
Hi, This patchset adds LU dedicated buffer mode support for WriteBooster. In the meanwhile, enable WriteBooster capability on MediaTek UFS platforms. v4 -> v5: - Check LUN ID for available WriteBooster buffer only from 0 to 7 according to spec (Avri Altman) - Skip checking any possible errors from ufshcd_read_unit_desc_param(hba, lun, UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS) in ufshcd_wb_probe() and check returned d_lu_wb_buf_alloc (shall be zero if error happens) (Avri Altman) v3 -> v4: - Introduce "fixup_dev_quirks" vops to allow vendors to fix and modify device quirks, and provide an initial vendor-specific device quirk table on MediaTek UFS platforms - Avoid relying on common device quirk table for pre-3.1 UFS device with non-standard WriteBooster support (Can Guo) - Fix comments for ufshcd_wb_probe() (Can Guo) - Make ufshcd_wb_get_flag_index() inline and fix ufshcd_is_wb_flags() (Avri Altman) v2 -> v3: - Introduce a device quirk to support WriteBooster in pre-3.1 UFS devices (Avri Altman) - Fix WriteBooster related sysfs nodes. Now all WriteBooster related sysfs nodes are specifically mapped to the LUN with WriteBooster enabled in LU Dedicated buffer mode (Avri Altman) v1 -> v2: - Change the definition name of WriteBooster buffer mode to correspond to specification (Bean Huo) - Add patch #5: "scsi: ufs: cleanup WriteBooster feature" Stanley Chu (8): scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices scsi: ufs: introduce fixup_dev_quirks vops scsi: ufs: export ufs_fixup_device_setup() function scsi: ufs-mediatek: add fixup_dev_quirks vops scsi: ufs: add "index" in parameter list of ufshcd_query_flag() scsi: ufs: add LU Dedicated buffer mode support for WriteBooster scsi: ufs-mediatek: enable WriteBooster capability scsi: ufs: cleanup WriteBooster feature drivers/scsi/ufs/ufs-mediatek.c | 25 - drivers/scsi/ufs/ufs-sysfs.c| 11 ++- drivers/scsi/ufs/ufs.h | 10 ++ drivers/scsi/ufs/ufs_quirks.h | 7 ++ drivers/scsi/ufs/ufshcd.c | 156 drivers/scsi/ufs/ufshcd.h | 20 +++- 6 files changed, 167 insertions(+), 62 deletions(-) -- 2.18.0
Re: [PATCH] staging: iio: ad2s1210: Fix SPI reading
On Wed, 29 Apr 2020 10:21:29 +0300 Alexandru Ardelean wrote: > From: Dragos Bogdan > > If the serial interface is used, the 8-bit address should be latched using > the rising edge of the WR/FSYNC signal. > > This basically means that a CS change is required between the first byte > sent, and the second one. > This change splits the single-transfer transfer of 2 bytes into 2 transfers > with a single byte, and CS change in-between. > > Signed-off-by: Dragos Bogdan > Signed-off-by: Alexandru Ardelean Fixes tag would have been nice. I've had a go by picking a patch where I refactored this code, but I think the issue probably predates that one. Its in 2011 so I doubt anyone will try going past that with backports ;) Applied to the fixes-togreg branch of iio.git and marked for stable. I'm guessing this means you have hardware and hope to get this one out of staging shortly? *crosses fingers* :) Jonathan > --- > drivers/staging/iio/resolver/ad2s1210.c | 17 - > 1 file changed, 12 insertions(+), 5 deletions(-) > > diff --git a/drivers/staging/iio/resolver/ad2s1210.c > b/drivers/staging/iio/resolver/ad2s1210.c > index 4b25a3a314ed..ed404355ea4c 100644 > --- a/drivers/staging/iio/resolver/ad2s1210.c > +++ b/drivers/staging/iio/resolver/ad2s1210.c > @@ -130,17 +130,24 @@ static int ad2s1210_config_write(struct ad2s1210_state > *st, u8 data) > static int ad2s1210_config_read(struct ad2s1210_state *st, > unsigned char address) > { > - struct spi_transfer xfer = { > - .len = 2, > - .rx_buf = st->rx, > - .tx_buf = st->tx, > + struct spi_transfer xfers[] = { > + { > + .len = 1, > + .rx_buf = &st->rx[0], > + .tx_buf = &st->tx[0], > + .cs_change = 1, > + }, { > + .len = 1, > + .rx_buf = &st->rx[1], > + .tx_buf = &st->tx[1], > + }, > }; > int ret = 0; > > ad2s1210_set_mode(MOD_CONFIG, st); > st->tx[0] = address | AD2S1210_MSB_IS_HIGH; > st->tx[1] = AD2S1210_REG_FAULT; > - ret = spi_sync_transfer(st->sdev, &xfer, 1); > + ret = spi_sync_transfer(st->sdev, xfers, 2); > if (ret < 0) > return ret; >
Re: [PATCH v3 6/7] ASoC: sun4i-i2s: Adjust regmap settings
Hi, On Mon, 27 Apr 2020 at 13:03, Chen-Yu Tsai wrote: > > On Sun, Apr 26, 2020 at 6:41 PM Clément Péron wrote: > > > > From: Marcus Cooper > > > > Bypass the regmap cache when flushing or reading the i2s FIFOs. > > > > Signed-off-by: Marcus Cooper > > Signed-off-by: Clément Péron > > Acked-by: Chen-Yu Tsai The SUN4I_I2S_FIFO_CTRL_REG is also missing. As some bits can self-clear by themselves. I will fix this in v4. Regards, Clement
Re: [PATCH] iio: adc: ad7768-1: Fix channel endian spec
On Wed, 29 Apr 2020 13:45:35 +0300 Sergiu Cuciurean wrote: > This change removes the endian description from the iio channel spec. > In this way, the default (IIO_CPU) endian will be used, matching the > be32_to_cpu() conversion from ad7768_spi_reg_read(). > > Fixes: 8a15c73a9bcfe ("iio: adc: Add AD7768-1 ADC basic support") > > Signed-off-by: Sergiu Cuciurean Hi Sergiu, The endian marking only applies to the push_to_buffers data. That is read from the hardware using spi_read, not the ad7768_spi_reg_read function. So logic above doesn't hold. Thanks, Jonathan > --- > drivers/iio/adc/ad7768-1.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c > index a0027797a7fe..99da13c3511a 100644 > --- a/drivers/iio/adc/ad7768-1.c > +++ b/drivers/iio/adc/ad7768-1.c > @@ -144,7 +144,6 @@ static const struct iio_chan_spec ad7768_channels[] = { > .realbits = 24, > .storagebits = 32, > .shift = 8, > - .endianness = IIO_BE, > }, > }, > };
Re: [PATCH v2] iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling
On Wed, 29 Apr 2020 14:29:08 +0200 Fabrice Gasnier wrote: > When the ADC is runtime suspended and starting a conversion, the stm32-adc > driver calls pm_runtime_get_sync() that gets cascaded to the parent > (e.g. runtime resume of stm32-adc-core driver). This also kicks the > autosuspend delay (e.g. 2s) of the parent. > Once the ADC is active, calling pm_runtime_get_sync() again (upon a new > capture) won't kick the autosuspend delay for the parent (stm32-adc-core > driver) as already active. > > Currently, this makes the stm32-adc-core driver go in suspend state > every 2s when doing slow polling. As an example, doing a capture, e.g. > cat in_voltageY_raw at a 0.2s rate, the auto suspend delay for the parent > isn't refreshed. Once it expires, the parent immediately falls into > runtime suspended state, in between two captures, as soon as the child > driver falls into runtime suspend state: > - e.g. after 2s, + child calls pm_runtime_put_autosuspend() + 100ms > autosuspend delay of the child. > - stm32-adc-core switches off regulators, clocks and so on. > - They get switched on back again 100ms later in this example (at 2.2s). > > So, use runtime_idle() callback in stm32-adc-core driver to call > pm_runtime_mark_last_busy() for the parent driver (stm32-adc-core), > to avoid this. > > Fixes: 9bdbb1139ca1 ("iio: adc: stm32-adc: add power management support") > > Signed-off-by: Fabrice Gasnier Whilst this seems 'sensible' to me, I really don't have a good enough grasp of runtime pm to be sure. I see something similar looking in the greybus driver, but not sure on the reason it is there. Hence, ideally looking for an ack from Rafael on this one! Thanks, Jonathan > --- > Changes in v2: > - Use runtime_idle callback in stm32-adc-core driver, instead of refreshing > last_busy from the child (for the parent) at many place. Initial patch v1 > looked like "somewhat adhoc solution" as commented by Jonathan. > --- > drivers/iio/adc/stm32-adc-core.c | 9 - > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/iio/adc/stm32-adc-core.c > b/drivers/iio/adc/stm32-adc-core.c > index 2df88d2..ebe5dbc 100644 > --- a/drivers/iio/adc/stm32-adc-core.c > +++ b/drivers/iio/adc/stm32-adc-core.c > @@ -803,6 +803,13 @@ static int stm32_adc_core_runtime_resume(struct device > *dev) > { > return stm32_adc_core_hw_start(dev); > } > + > +static int stm32_adc_core_runtime_idle(struct device *dev) > +{ > + pm_runtime_mark_last_busy(dev); > + > + return 0; > +} > #endif > > static const struct dev_pm_ops stm32_adc_core_pm_ops = { > @@ -810,7 +817,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = { > pm_runtime_force_resume) > SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend, > stm32_adc_core_runtime_resume, > -NULL) > +stm32_adc_core_runtime_idle) > }; > > static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
Re: [PATCH v4] checkpatch: add support to check 'Fixes:' tag format
On Sat, May 02, 2020 at 09:40:24PM +0200, Markus Elfring wrote: > > > > + $diagnostics .= "Missing a pair of parentheses > > '()' or a pair of double quotation marks (\"\").\n"; > > Can such a message trigger any more thoughts and development ideas? No, I don't think so. '(" ... ")' is the minimum interface between analyser (checkpatch) and commit id description (normal commit id and 'Fixes:' tag) about the title, it is very difficult if not impossible to guess the title boundary and whether it is the *REAL* title that folllow the SHA1 without this precondition, and it is more difficult to do it when we need to support title which across lines in the normal commit id description. At last I really doubt the benefit it brings deserves the complexity and the current diagnostics info is enough clear for most situation. Thanks.
[PATCH v2] checkpatch: fix can't check for too long invalid commit id
The current UNKNOWN_COMMIT_ID doesn't check for 41+ length commit id, and although GIT_COMMIT_ID will check for 41+ length commit id, but it willn't warn anything about it due to 41+ length commit will never be defined. This patch moves the unknown commit id check for normal commit description to GIT_COMMIT_ID, and uses ERROR instead of WARN, because unknown commit id is total useless to track change history in changelog, it deserves the ERROR. Signed-off-by: Wang YanQing --- v2: 1: Fix annonying "Invalid commit id" reports for non commit id number string. 2: Fix indentaton issue, reported by Joe Perches. 3: Reword the error message in code, suggested by Joe Perches. 4: Delete unnecessary capture group in UNKNOWN_COMMIT_ID, suggested by Joe Perches. scripts/checkpatch.pl | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 23a001a..9b47584 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2829,18 +2829,21 @@ sub process { my $space = 1; my $hasdesc = 0; my $hasparens = 0; + my $hasprefix = 1; my $id = '0123456789ab'; my $orig_desc = "commit description"; my $description = ""; + my $sha1_length_min = 12; if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { $init_char = $1; $orig_commit = lc($2); } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { $orig_commit = lc($1); + $hasprefix = 0; } - $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); + $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{$sha1_length_min,40}/i); $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); @@ -2865,10 +2868,21 @@ sub process { ($id, $description) = git_commit_info($orig_commit, $id, $orig_desc); + if ($hasprefix && !defined($id)) { + if ($long) { + ERROR("GIT_COMMIT_ID", + "Invalid commit id '$orig_commit' length '" . length($orig_commit) . "' exceeds allowed maxium of 40 + ($sha1_length_min+ chars of sha1 is recommended).\n" . $herecurr); + } else { + ERROR("GIT_COMMIT_ID", + "Unknown commit id '$orig_commit', maybe rebased or not pulled?\n" . $herecurr); + } + } + if (defined($id) && - ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) { + ($short || $space || $case || ($orig_desc ne $description) || !$hasparens)) { ERROR("GIT_COMMIT_ID", - "Please use git commit description style 'commit <12+ chars of sha1> (\"\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); + "Please use git commit description style 'commit <$sha1_length_min+ chars of sha1> (\"\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); } } @@ -2969,13 +2983,13 @@ sub process { } # check for invalid commit id - if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) { + if ($in_commit_log && $line =~ /^fixes:\s+([0-9a-f]{6,40})\b/i) { my $id; my $description; - ($id, $description) = git_commit_info($2, undef, undef); + ($id, $description) = git_commit_info($1, undef, undef); if (!defined($id)) { WARN("UNKNOWN_COMMIT_ID", -"Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr); +"Unknown commit id '$1', maybe rebased or not pulled?\n" . $herecurr); } } -- 1.8.5.6.2.g3d8a54e.dirty
Re: [PATCH v2 3/4] iio: accel: wsen-itds accel documentation
On Wed, 29 Apr 2020 15:39:42 +0200 Saravanan Sekar wrote: > Add documentation about device operating mode and output data range > supported according to operating mode > > Signed-off-by: Saravanan Sekar > --- > .../ABI/testing/sysfs-bus-iio-wsen-itds | 23 +++ > 1 file changed, 23 insertions(+) > create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-wsen-itds > > diff --git a/Documentation/ABI/testing/sysfs-bus-iio-wsen-itds > b/Documentation/ABI/testing/sysfs-bus-iio-wsen-itds > new file mode 100644 > index ..5979f2b8aa1a > --- /dev/null > +++ b/Documentation/ABI/testing/sysfs-bus-iio-wsen-itds > @@ -0,0 +1,23 @@ > +What: > /sys/bus/iio/devices/iio\:device0/in_accel_samp_freq_available > +KernelVersion: 5.7 > +Contact: linux-...@vger.kernel.org > +Description: > + Reading gives range of sample frequencies available for current > operating mode > + after one data has generated. This is standard ABI so should be the main docs, not here. It also takes absolute precedence over the power modes (as mentioned below, no standard userspace will be able to use those). So if the frequency is only available in high perf mode, then we change to high perf mode. > + > + Access: Read > + Valid values: represented in Hz > + - range [12.5, 1600] for high permormance mode > + - range [1.6, 200] for normal/low power mode > + > +What:/sys/bus/iio/devices/iio\:device0/operating_mode > +KernelVersion: 5.7 > +Contact: linux-...@vger.kernel.org > +Description: > + Represents the device operating mode. High performance mode > gives high output > + data rate and low noise compared to normal mode. Normal mode > consumes less > + current. In single shot device enters to lowpower after one > data has > + generated. > + > + Access: Read, Write > + Valid values: "lowpower", "normal", "high_perf", "single_shot" The issue with these sort of 'mode' interface is almost no userspace will ever use them. They are too unpredictable across different types of devices. Some of these should also not be exposed to userspace anyway as they are about 'how' you are using the driver. For example, if you aren't doing triggered capture then single_shot is almost always the correct option. Annoyingly I see high performance mode gives lower noise... So no need to expose single_shot to userspace. For the others we are just looking at different power vs speed and accuracy trade offs. Those are better exposed by what they effect. Here the big control for that is sampling frequency. So if we assume the user is never going to touch this control (if it's even there) then we probably want to assume they want the best possible accuracy for whatever frequency they are running at. So transition across the modes to provide that. Should we ever support low power mode? It sounds nice on paper, but in reality userspace won't use so I suspect we should just drop it - certainly in an initial patch submission (as it will hold up acceptance). Even if we did support it, as mentioned above ABI controls will take precedence so we are looking at a 'hint' not a control of mode. ABI is a pain, and we will put a lot of effort into not expanding it unless there is a good usecase plus no way of mapping to existing ABI. Jonathan
[PATCH v4 0/6] DVFS for IO devices on sdm845 and sc7180
Changes in v4: 1. Fixed all review feedback on v3 2. Dropped the dts patches, will post as a seperate series once driver changes are reviewed and merged. The driver changes without DT updates to include OPP tables will have zero functional change. 3. Dropped the mmc/sdhc patch, which is a standalone patch. will repost if needed seperately. Changes in v3: 1. Added better error handling for dev_pm_opp_of_add_table() 2. Some minor changes and fixes in 'PATCH 12/17' as compared to v2 3. Dropped the mmc patch picked up by Ulf [2] Changes in v2: 1. Added error handling for dev_pm_opp_set_clkname() and dev_pm_opp_of_add_table() 2. Used dev_pm_opp_put_clkname() in the cleanup path 3. Dropped the OPP patch pulled in by Viresh [1] 4. Dropped the UFS patches since they had some major rework needed because of changes that were merged in the merge window and I don't have a UFS device currently to validate the changes. We have had support added in the OPP core for a while now to support DVFS for IO devices, and this series uses that infrastructure to add DVFS support for various IO devices in sdm845 and sc7180 SoCs. [1] https://lkml.org/lkml/2020/4/14/98 [2] https://lore.kernel.org/patchwork/patch/1226381/ Rajendra Nayak (6): tty: serial: qcom_geni_serial: Use OPP API to set clk/perf state spi: spi-geni-qcom: Use OPP API to set clk/perf state drm/msm/dpu: Use OPP API to set clk/perf state drm/msm: dsi: Use OPP API to set clk/perf state media: venus: core: Add support for opp tables/perf voting spi: spi-qcom-qspi: Use OPP API to set clk/perf state drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c| 33 --- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h| 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 25 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h| 4 ++ drivers/gpu/drm/msm/dsi/dsi.h | 2 + drivers/gpu/drm/msm/dsi/dsi_cfg.c | 4 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 58 ++ drivers/media/platform/qcom/venus/core.c | 28 + drivers/media/platform/qcom/venus/core.h | 5 +++ drivers/media/platform/qcom/venus/pm_helpers.c | 54 ++-- drivers/spi/spi-geni-qcom.c| 26 ++-- drivers/spi/spi-qcom-qspi.c| 29 - drivers/tty/serial/qcom_geni_serial.c | 34 --- include/linux/qcom-geni-se.h | 4 ++ 15 files changed, 259 insertions(+), 51 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
[PATCH v4 1/6] tty: serial: qcom_geni_serial: Use OPP API to set clk/perf state
geni serial needs to express a perforamnce state requirement on CX powerdomain depending on the frequency of the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak Reviewed-by: Matthias Kaehlcke Cc: Greg Kroah-Hartman Cc: Akash Asthana Cc: linux-ser...@vger.kernel.org --- drivers/tty/serial/qcom_geni_serial.c | 34 +- include/linux/qcom-geni-se.h | 4 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 6119090..dd3d1ba 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -961,7 +962,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, goto out_restart_rx; uport->uartclk = clk_rate; - clk_set_rate(port->se.clk, clk_rate); + dev_pm_opp_set_rate(uport->dev, clk_rate); ser_clk_cfg = SER_CLK_EN; ser_clk_cfg |= clk_div << CLK_DIV_SHFT; @@ -1198,8 +1199,11 @@ static void qcom_geni_serial_pm(struct uart_port *uport, if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) geni_se_resources_on(&port->se); else if (new_state == UART_PM_STATE_OFF && - old_state == UART_PM_STATE_ON) + old_state == UART_PM_STATE_ON) { + /* Drop the performance state vote */ + dev_pm_opp_set_rate(uport->dev, 0); geni_se_resources_off(&port->se); + } } static const struct uart_ops qcom_geni_console_pops = { @@ -1318,13 +1322,25 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap")) port->cts_rts_swap = true; + port->se.opp_table = dev_pm_opp_set_clkname(&pdev->dev, "se"); + if (IS_ERR(port->se.opp_table)) + return PTR_ERR(port->se.opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(&pdev->dev); + if (!ret) { + port->se.has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(&pdev->dev, "invalid OPP table in device tree\n"); + return ret; + } + uport->private_data = drv; platform_set_drvdata(pdev, port); port->handle_rx = console ? handle_rx_console : handle_rx_uart; ret = uart_add_one_port(drv, uport); if (ret) - return ret; + goto err; irq_set_status_flags(uport->irq, IRQ_NOAUTOEN); ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr, @@ -1332,7 +1348,7 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) if (ret) { dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret); uart_remove_one_port(drv, uport); - return ret; + goto err; } /* @@ -1349,11 +1365,16 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) if (ret) { device_init_wakeup(&pdev->dev, false); uart_remove_one_port(drv, uport); - return ret; + goto err; } } return 0; +err: + if (port->se.has_opp_table) + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(port->se.opp_table); + return ret; } static int qcom_geni_serial_remove(struct platform_device *pdev) @@ -1361,6 +1382,9 @@ static int qcom_geni_serial_remove(struct platform_device *pdev) struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); struct uart_driver *drv = port->uport.private_data; + if (port->se.has_opp_table) + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(port->se.opp_table); dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); uart_remove_one_port(drv, &port->uport); diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index dd46494..6b78094 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -33,6 +33,8 @@ struct clk; * @clk: Handle to the core serial engine clock * @num_clk_levels:Number of valid clock levels in clk_perf_tbl * @clk_perf_tbl: Table of clock frequency input to serial engine clock + * @opp_table: Pointer to the OPP table + * @has_opp_table: Specifies if the SE has an OPP table */ struct geni_se { void __iomem *base; @@ -41,6 +43,8 @@ struct geni_se { struct clk *clk; unsigned int num_clk_levels; unsigned long *clk_perf_tbl; +
[PATCH v4 3/6] drm/msm/dpu: Use OPP API to set clk/perf state
On some qualcomm platforms DPU needs to express a performance state requirement on a power domain depending on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak Reviewed-by: Rob Clark Reviewed-by: Matthias Kaehlcke Cc: Rob Clark Cc: Sean Paul Cc: dri-de...@lists.freedesktop.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 33 --- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 25 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 11f2beb..fe5717df 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -239,7 +240,7 @@ static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate) rate = core_clk->max_rate; core_clk->rate = rate; - return msm_dss_clk_set_rate(core_clk, 1); + return dev_pm_opp_set_rate(&kms->pdev->dev, core_clk->rate); } static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c index 078afc5..b9a4bf8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c @@ -51,39 +51,6 @@ int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk) return rc; } -int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk) -{ - int i, rc = 0; - - for (i = 0; i < num_clk; i++) { - if (clk_arry[i].clk) { - if (clk_arry[i].type != DSS_CLK_AHB) { - DEV_DBG("%pS->%s: '%s' rate %ld\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name, - clk_arry[i].rate); - rc = clk_set_rate(clk_arry[i].clk, - clk_arry[i].rate); - if (rc) { - DEV_ERR("%pS->%s: %s failed. rc=%d\n", - __builtin_return_address(0), - __func__, - clk_arry[i].clk_name, rc); - break; - } - } - } else { - DEV_ERR("%pS->%s: '%s' is not available\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name); - rc = -EPERM; - break; - } - } - - return rc; -} - int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable) { int i, rc = 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h index e6b5c77..ca25c90 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h @@ -33,7 +33,6 @@ struct dss_module_power { int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk); void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk); -int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk); int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable); int msm_dss_parse_clock(struct platform_device *pdev, struct dss_module_power *mp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ce19f1d..f16d715 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -1033,11 +1034,23 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) if (!dpu_kms) return -ENOMEM; + dpu_kms->opp_table = dev_pm_opp_set_clkname(dev, "core"); + if (IS_ERR(dpu_kms->opp_table)) + return PTR_ERR(dpu_kms->opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(dev); + if (!ret) { + dpu_kms->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(dev, "invalid OPP table in device tree\n"); + return ret; + } + mp = &dpu_kms->mp; ret = msm_dss_parse_clock(pdev, mp); if (ret) {
[PATCH v4 2/6] spi: spi-geni-qcom: Use OPP API to set clk/perf state
geni spi needs to express a perforamnce state requirement on CX depending on the frequency of the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak Reviewed-by: Matthias Kaehlcke Cc: Mark Brown Cc: Alok Chauhan Cc: Akash Asthana Cc: linux-...@vger.kernel.org --- This patch has a dependency on the 'PATCH 1/6' in this series, due to the changes in include/linux/qcom-geni-se.h Its ideal if this and the previous patch gets merged via the msm tree (once reviewed and ack'ed) Greg has already responded he is fine with it for serial. drivers/spi/spi-geni-qcom.c | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index c397242..bc2916f 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -95,7 +96,6 @@ static int get_spi_clk_cfg(unsigned int speed_hz, { unsigned long sclk_freq; unsigned int actual_hz; - struct geni_se *se = &mas->se; int ret; ret = geni_se_clk_freq_match(&mas->se, @@ -112,9 +112,9 @@ static int get_spi_clk_cfg(unsigned int speed_hz, dev_dbg(mas->dev, "req %u=>%u sclk %lu, idx %d, div %d\n", speed_hz, actual_hz, sclk_freq, *clk_idx, *clk_div); - ret = clk_set_rate(se->clk, sclk_freq); + ret = dev_pm_opp_set_rate(mas->dev, sclk_freq); if (ret) - dev_err(mas->dev, "clk_set_rate failed %d\n", ret); + dev_err(mas->dev, "dev_pm_opp_set_rate failed %d\n", ret); return ret; } @@ -561,6 +561,17 @@ static int spi_geni_probe(struct platform_device *pdev) mas->se.wrapper = dev_get_drvdata(dev->parent); mas->se.base = base; mas->se.clk = clk; + mas->se.opp_table = dev_pm_opp_set_clkname(&pdev->dev, "se"); + if (IS_ERR(mas->se.opp_table)) + return PTR_ERR(mas->se.opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(&pdev->dev); + if (!ret) { + mas->se.has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(&pdev->dev, "invalid OPP table in device tree\n"); + return ret; + } spi->bus_num = -1; spi->dev.of_node = dev->of_node; @@ -596,6 +607,9 @@ static int spi_geni_probe(struct platform_device *pdev) spi_geni_probe_runtime_disable: pm_runtime_disable(dev); spi_master_put(spi); + if (mas->se.has_opp_table) + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(mas->se.opp_table); return ret; } @@ -604,6 +618,9 @@ static int spi_geni_remove(struct platform_device *pdev) struct spi_master *spi = platform_get_drvdata(pdev); struct spi_geni_master *mas = spi_master_get_devdata(spi); + if (mas->se.has_opp_table) + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(mas->se.opp_table); /* Unregister _before_ disabling pm_runtime() so we stop transfers */ spi_unregister_master(spi); @@ -617,6 +634,9 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev) struct spi_master *spi = dev_get_drvdata(dev); struct spi_geni_master *mas = spi_master_get_devdata(spi); + /* Drop the performance state vote */ + dev_pm_opp_set_rate(dev, 0); + return geni_se_resources_off(&mas->se); } -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
[PATCH v4 4/6] drm/msm: dsi: Use OPP API to set clk/perf state
On SDM845 DSI needs to express a perforamnce state requirement on a power domain depending on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak Cc: Rob Clark Cc: Sean Paul Cc: dri-de...@lists.freedesktop.org --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_cfg.c | 4 +-- drivers/gpu/drm/msm/dsi/dsi_host.c | 58 ++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 4de771d..ba7583c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -180,10 +180,12 @@ int msm_dsi_runtime_suspend(struct device *dev); int msm_dsi_runtime_resume(struct device *dev); int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host); +int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host); +void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host); int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size); int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size); void *dsi_tx_buf_get_6g(struct msm_dsi_host *msm_host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 813d69d..773c4fe 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -210,9 +210,9 @@ static const struct msm_dsi_host_cfg_ops msm_dsi_6g_host_ops = { }; static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_host_ops = { - .link_clk_set_rate = dsi_link_clk_set_rate_6g, + .link_clk_set_rate = dsi_link_clk_set_rate_6g_v2, .link_clk_enable = dsi_link_clk_enable_6g, - .link_clk_disable = dsi_link_clk_disable_6g, + .link_clk_disable = dsi_link_clk_disable_6g_v2, .clk_init_ver = dsi_clk_init_6g_v2, .tx_buf_alloc = dsi_tx_buf_alloc_6g, .tx_buf_get = dsi_tx_buf_get_6g, diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 11ae5b8..d5f3dcd 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -111,6 +112,9 @@ struct msm_dsi_host { struct clk *pixel_clk_src; struct clk *byte_intf_clk; + struct opp_table *opp_table; + bool has_opp_table; + u32 byte_clk_rate; u32 pixel_clk_rate; u32 esc_clk_rate; @@ -537,6 +541,38 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) return 0; } +int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host) +{ + int ret; + struct device *dev = &msm_host->pdev->dev; + + DBG("Set clk rates: pclk=%d, byteclk=%d", + msm_host->mode->clock, msm_host->byte_clk_rate); + + ret = dev_pm_opp_set_rate(dev, msm_host->byte_clk_rate); + if (ret) { + pr_err("%s: dev_pm_opp_set_rate failed %d\n", __func__, ret); + return ret; + } + + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); + if (ret) { + pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); + return ret; + } + + if (msm_host->byte_intf_clk) { + ret = clk_set_rate(msm_host->byte_intf_clk, + msm_host->byte_clk_rate / 2); + if (ret) { + pr_err("%s: Failed to set rate byte intf clk, %d\n", + __func__, ret); + return ret; + } + } + + return 0; +} int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) { @@ -665,6 +701,13 @@ void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); } +void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host) +{ + /* Drop the performance state vote */ + dev_pm_opp_set_rate(&msm_host->pdev->dev, 0); + dsi_link_clk_disable_6g(msm_host); +} + void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) { clk_disable_unprepare(msm_host->pixel_clk); @@ -1879,6 +1922,18 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) goto fail; } + msm_host->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "byte"); + if (IS_ERR(msm_host->opp_table)) + return PTR_ERR(msm_host->opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(&pdev->dev); + if (!ret) { + msm_host->has_opp_table = true; + } else
Re: [PATCH] rtc: mc13xxx: fix a double-unlock issue
> … To fix this problem, > we need to call mc13xxx_lock() again in this error path. How do you think about a wording variant like the following? Change description: … Thus add a call of the function “mc13xxx_lock” in an if branch for the completion of the exception handling. Would you like to add the tag “Fixes”? Regards, Markus
[PATCH v4 6/6] spi: spi-qcom-qspi: Use OPP API to set clk/perf state
QSPI needs to vote on a performance state of a power domain depending on the clock rate. Add support for it by specifying the perf state/clock rate as an OPP table in device tree. Signed-off-by: Rajendra Nayak Cc: Mark Brown Cc: Alok Chauhan Cc: Akash Asthana Cc: linux-...@vger.kernel.org --- drivers/spi/spi-qcom-qspi.c | 29 - 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index 3c4f83b..eb53c00 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -139,6 +140,8 @@ struct qcom_qspi { struct device *dev; struct clk_bulk_data *clks; struct qspi_xfer xfer; + struct opp_table *opp_table; + bool has_opp_table; /* Lock to protect xfer and IRQ accessed registers */ spinlock_t lock; }; @@ -235,7 +238,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master, speed_hz = xfer->speed_hz; /* In regular operation (SBL_EN=1) core must be 4x transfer clock */ - ret = clk_set_rate(ctrl->clks[QSPI_CLK_CORE].clk, speed_hz * 4); + ret = dev_pm_opp_set_rate(ctrl->dev, speed_hz * 4); if (ret) { dev_err(ctrl->dev, "Failed to set core clk %d\n", ret); return ret; @@ -481,6 +484,20 @@ static int qcom_qspi_probe(struct platform_device *pdev) master->handle_err = qcom_qspi_handle_err; master->auto_runtime_pm = true; + ctrl->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "core"); + if (IS_ERR(ctrl->opp_table)) { + ret = PTR_ERR(ctrl->opp_table); + goto exit_probe_master_put; + } + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(&pdev->dev); + if (!ret) { + ctrl->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(&pdev->dev, "invalid OPP table in device tree\n"); + goto exit_probe_master_put; + } + pm_runtime_enable(dev); ret = spi_register_master(master); @@ -488,6 +505,9 @@ static int qcom_qspi_probe(struct platform_device *pdev) return 0; pm_runtime_disable(dev); + if (ctrl->has_opp_table) + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(ctrl->opp_table); exit_probe_master_put: spi_master_put(master); @@ -498,6 +518,11 @@ static int qcom_qspi_probe(struct platform_device *pdev) static int qcom_qspi_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); + struct qcom_qspi *ctrl = spi_master_get_devdata(master); + + if (ctrl->has_opp_table) + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(ctrl->opp_table); /* Unregister _before_ disabling pm_runtime() so we stop transfers */ spi_unregister_master(master); @@ -512,6 +537,8 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev) struct spi_master *master = dev_get_drvdata(dev); struct qcom_qspi *ctrl = spi_master_get_devdata(master); + /* Drop the performance state vote */ + dev_pm_opp_set_rate(dev, 0); clk_bulk_disable_unprepare(QSPI_NUM_CLKS, ctrl->clks); return 0; -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
[PATCH v4 5/6] media: venus: core: Add support for opp tables/perf voting
Add support to add OPP tables and perf voting on the OPP powerdomain. This is needed so venus votes on the corresponding performance state for the OPP powerdomain along with setting the core clock rate. Signed-off-by: Rajendra Nayak Cc: Stanimir Varbanov Cc: linux-me...@vger.kernel.org --- drivers/media/platform/qcom/venus/core.c | 28 + drivers/media/platform/qcom/venus/core.h | 5 +++ drivers/media/platform/qcom/venus/pm_helpers.c | 54 -- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 194b10b9..6f72e99 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -214,6 +215,20 @@ static int venus_probe(struct platform_device *pdev) if (!core->pm_ops) return -ENODEV; + core->opp_table = dev_pm_opp_set_clkname(dev, "core"); + if (IS_ERR(core->opp_table)) + return PTR_ERR(core->opp_table); + + if (core->res->opp_pmdomain) { + ret = dev_pm_opp_of_add_table(dev); + if (!ret) { + core->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(dev, "invalid OPP table in device tree\n"); + return ret; + } + } + if (core->pm_ops->core_get) { ret = core->pm_ops->core_get(dev); if (ret) @@ -301,6 +316,9 @@ static int venus_probe(struct platform_device *pdev) err_venus_shutdown: venus_shutdown(core); err_runtime_disable: + if (core->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(core->opp_table); pm_runtime_set_suspended(dev); pm_runtime_disable(dev); hfi_destroy(core); @@ -326,6 +344,10 @@ static int venus_remove(struct platform_device *pdev) venus_firmware_deinit(core); + if (core->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(core->opp_table); + pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -350,6 +372,10 @@ static __maybe_unused int venus_runtime_suspend(struct device *dev) if (ret) return ret; + /* Drop the performance state vote */ + if (core->opp_pmdomain) + dev_pm_opp_set_rate(dev, 0); + if (pm_ops->core_power) ret = pm_ops->core_power(dev, POWER_OFF); @@ -511,6 +537,7 @@ static const struct venus_resources sdm845_res_v2 = { .vcodec_clks_num = 2, .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" }, .vcodec_pmdomains_num = 3, + .opp_pmdomain = (const char *[]) { "opp-pd", NULL }, .vcodec_num = 2, .max_load = 3110400,/* 4096x2160@90 */ .hfi_version = HFI_VERSION_4XX, @@ -556,6 +583,7 @@ static const struct venus_resources sc7180_res = { .vcodec_clks_num = 2, .vcodec_pmdomains = { "venus", "vcodec0" }, .vcodec_pmdomains_num = 2, + .opp_pmdomain = (const char *[]) { "opp-pd", NULL }, .vcodec_num = 1, .hfi_version = HFI_VERSION_4XX, .vmem_id = VIDC_RESOURCE_NONE, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index bd3ac6a..cc1d511 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -62,6 +62,7 @@ struct venus_resources { unsigned int vcodec_clks_num; const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX]; unsigned int vcodec_pmdomains_num; + const char **opp_pmdomain; unsigned int vcodec_num; enum hfi_version hfi_version; u32 max_load; @@ -144,8 +145,12 @@ struct venus_core { struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; struct icc_path *video_path; struct icc_path *cpucfg_path; + struct opp_table *opp_table; + bool has_opp_table; struct device_link *pd_dl_venus; struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX]; + struct device_link *opp_dl_venus; + struct device *opp_pmdomain; struct video_device *vdev_dec; struct video_device *vdev_enc; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index abf9315..30600bc 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core) static int core_clks_set_rate(struct venus_core *core, unsigned long freq) { - struct clk *cl
[PATCH] i2c: uniphier: Remove superfluous error message in uniphier_i2c_probe()
The function platform_get_irq can log an error by itself. This omit a redundant message for exception handling in the calling function. Suggested by Coccinelle. Signed-off-by: Aishwarya Ramakrishnan --- drivers/i2c/busses/i2c-uniphier.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 668b1fa2b0ef..ee00a44bf4c7 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -324,10 +324,8 @@ static int uniphier_i2c_probe(struct platform_device *pdev) return PTR_ERR(priv->membase); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to get IRQ number\n"); + if (irq < 0) return irq; - } if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed)) bus_speed = I2C_MAX_STANDARD_MODE_FREQ; -- 2.17.1
[PATCH 2/2] clk: at91: pmc: decrement node's refcount
of_find_matching_node() increment node's refcount. Call of_node_put() to decrement it after it was used. Signed-off-by: Claudiu Beznea --- drivers/clk/at91/pmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index bf0570e66fc1..e164069c81bd 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -278,6 +278,7 @@ static int __init pmc_register_ops(void) return -ENODEV; pmcreg = device_node_to_regmap(np); + of_node_put(np); if (IS_ERR(pmcreg)) return PTR_ERR(pmcreg); -- 2.7.4
[PATCH 1/2] clk: at91: pmc: do not continue if compatible not located
pmc_register_ops() is called for all AT91 devices. Return -ENODEV in case of_find_matching_node() returns NULL. Signed-off-by: Claudiu Beznea --- drivers/clk/at91/pmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index b71515acdec1..bf0570e66fc1 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -274,6 +274,8 @@ static int __init pmc_register_ops(void) struct device_node *np; np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids); + if (!np) + return -ENODEV; pmcreg = device_node_to_regmap(np); if (IS_ERR(pmcreg)) -- 2.7.4
[git pull] IOMMU Fixes for Linux v5.7-rc3
Hi Linus, The following changes since commit 6a8b55ed4056ea5559ebe4f6a4b247f627870d4c: Linux 5.7-rc3 (2020-04-26 13:51:02 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git tags/iommu-fixes-v5.7-rc3 for you to fetch changes up to b52649aee6243ea661905bdc5fbe28cc5f6dec76: iommu/qcom: Fix local_base status check (2020-05-01 13:37:23 +0200) IOMMU Fixes for Linux v5.7-rc3 Including: - Fix for a memory leak when dev_iommu gets freed and a sub-pointer does not. - Build dependency fixes for Mediatek, spapr_tce, and Intel IOMMU driver. - Export iommu_group_get_for_dev() only for GPLed modules - Fix for AMD IOMMU interrupt remapping when x2apic is enabled - Fix for error path in the QCOM IOMMU driver probe function Geert Uytterhoeven (1): iommu/mediatek: Fix MTK_IOMMU dependencies Greg Kroah-Hartman (1): iommu: Properly export iommu_group_get_for_dev() Kevin Hao (1): iommu: Fix the memory leak in dev_iommu_free() Krzysztof Kozlowski (1): iommu: spapr_tce: Disable compile testing to fix build on book3s_32 config Lu Baolu (1): iommu/vt-d: Use right Kconfig option name Suravee Suthikulpanit (1): iommu/amd: Fix legacy interrupt remapping for x2APIC-enabled system Tang Bin (1): iommu/qcom: Fix local_base status check drivers/iommu/Kconfig | 4 ++-- drivers/iommu/amd_iommu_init.c | 2 +- drivers/iommu/intel-iommu.c| 4 ++-- drivers/iommu/iommu.c | 3 ++- drivers/iommu/qcom_iommu.c | 5 - 5 files changed, 11 insertions(+), 7 deletions(-) Please pull. There are also some race condition fixes for the AMD IOMMU driver pending, but I wait for more testing feedback from Qian before sending them your way, so they are not included here. Thanks, Joerg signature.asc Description: Digital signature
Re: [v4] checkpatch: add support to check 'Fixes:' tag format
>>> + $diagnostics .= "Missing a pair of parentheses >>> '()' or a pair of double quotation marks (\"\").\n"; >> >> Can such a message trigger any more thoughts and development ideas? > > No, I don't think so. '(" ... ")' is the minimum interface between analyser > (checkpatch) and commit id description (normal commit id and 'Fixes:' tag) * I am proposing to recheck the influence of quotation character alternatives also at this place. * How do you think about to provide an information without the word “or” in error messages? > about the title, it is very difficult if not impossible to guess the title > boundary and whether it is the *REAL* title that folllow the SHA1 without > this precondition, I find this concern reasonable. > and it is more difficult to do it when we need to support > title which across lines in the normal commit id description. I imagine that further software design options can be considered. > At last I really doubt the benefit it brings deserves the complexity and the > current diagnostics info is enough clear for most situation. * Will a safer data format description trigger corresponding efforts? * Will the structure of the commit title matter? * Would you like to improve checks (and program organisation) besides the application of regular expressions? Regards, Markus
[PATCH net v3] net: macb: fix an issue about leak related system resources
A call of the function macb_init() can fail in the function fu540_c000_init. The related system resources were not released then. use devm_platform_ioremap_resource() to replace ioremap() to fix it. Fixes: c218ad559020ff9 ("macb: Add support for SiFive FU540-C000") Cc: Andy Shevchenko Reviewed-by: Yash Shah Suggested-by: Nicolas Ferre Suggested-by: Andy Shevchenko Signed-off-by: Dejin Zheng --- v2 -> v3: - use IS_ERR() and PTR_ERR() for error handling by Nicolas's suggestion. Thanks Nicolas! v1 -> v2: - Nicolas and Andy suggest use devm_platform_ioremap_resource() to repalce devm_ioremap() to fix this issue. Thanks Nicolas and Andy. - Yash help me to review this patch, Thanks Yash! drivers/net/ethernet/cadence/macb_main.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index a0e8c5bbabc0..f040a36d6e54 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -4172,15 +4172,9 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk, static int fu540_c000_init(struct platform_device *pdev) { - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) - return -ENODEV; - - mgmt->reg = ioremap(res->start, resource_size(res)); - if (!mgmt->reg) - return -ENOMEM; + mgmt->reg = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(mgmt->reg)) + return PTR_ERR(mgmt->reg); return macb_init(pdev); } -- 2.25.0
[PATCH] i2c: lpc2k: Remove superfluous error message in i2c_lpc2k_probe()
The function platform_get_irq can log an error by itself. This omit a redundant message for exception handling in the calling function. Suggested by Coccinelle. Signed-off-by: Aishwarya Ramakrishnan --- drivers/i2c/busses/i2c-lpc2k.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 13b0c12e2dba..43dc9b7043e4 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -362,10 +362,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) return PTR_ERR(i2c->base); i2c->irq = platform_get_irq(pdev, 0); - if (i2c->irq < 0) { - dev_err(&pdev->dev, "can't get interrupt resource\n"); + if (i2c->irq < 0) return i2c->irq; - } init_waitqueue_head(&i2c->wait); -- 2.17.1
Re: [PATCH v23 02/16] leds: multicolor: Introduce a multicolor class definition
Jacek On 5/2/20 4:51 PM, Jacek Anaszewski wrote: Dan, I've converted drivers/leds/leds-an30259a.c to LED mc framework and tested it on Samsung Galaxy S3 (exysnos4412-trats2 board). Works as expected. And now the framework usability is indeed neater. One thing to improve: LED mc based drivers' entries in Kconfig should have this dependency: depends on LEDS_CLASS_MULTI_COLOR || !LEDS_CLASS_MULTI_COLOR It is required to enforce building driver as a module if LED mc framework is configured as such. Do you think the FLASH class needs this as well? If so I will send this in a separate patch With this (and DT bindings nits) addressed, for patches 1-6: Acked-by: Jacek Anaszewski Ack It's been a long journey. Thank you for your determination to drive this work to the end. Ack to that. Dan
[PATCH v24 01/16] dt: bindings: Add multicolor class dt bindings documention
Add DT bindings for the LEDs multicolor class framework. Add multicolor ID to the color ID list for device tree bindings. CC: Rob Herring Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- .../bindings/leds/leds-class-multicolor.yaml | 71 +++ drivers/leds/led-core.c | 1 + include/dt-bindings/leds/common.h | 3 +- 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml diff --git a/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml new file mode 100644 index ..16ffafc062ad --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/leds-class-multicolor.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Common properties for the multicolor LED class. + +maintainers: + - Dan Murphy + +description: | + Bindings for multi color LEDs show how to describe current outputs of + either integrated multi-color LED elements (like RGB, RGBW, RGBWA-UV + etc.) or standalone LEDs, to achieve logically grouped multi-color LED + modules. This is achieved by adding multi-led nodes layer to the + monochrome LED bindings. + The nodes and properties defined in this document are unique to the multicolor + LED class. Common LED nodes and properties are inherited from the common.txt + within this documentation directory. + +properties: + color: +description: | + For multicolor LED support this property should be defined as + LED_COLOR_ID_MULTI and further definition can be found in + include/linux/leds/common.h. + +required: + - color + +examples: + - | +#include +i2c { +#address-cells = <1>; +#size-cells = <0>; + +led-controller@14 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,lp5009"; + reg = <0x14>; + +multi-led@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + color = ; + function = LED_FUNCTION_CHARGING; + + led@0 { +reg = <0>; +color = ; + }; + + led@1 { +reg = <1>; +color = ; + }; + + led@2 { +reg = <2>; +color = ; + }; +}; + }; +}; + +additionalProperties: false +... diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index f1f718dbe0f8..846248a0693d 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -34,6 +34,7 @@ const char * const led_colors[LED_COLOR_ID_MAX] = { [LED_COLOR_ID_VIOLET] = "violet", [LED_COLOR_ID_YELLOW] = "yellow", [LED_COLOR_ID_IR] = "ir", + [LED_COLOR_ID_MULTI] = "multicolor", }; EXPORT_SYMBOL_GPL(led_colors); diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h index 0ce7dfc00dcb..a463ce6a8794 100644 --- a/include/dt-bindings/leds/common.h +++ b/include/dt-bindings/leds/common.h @@ -30,7 +30,8 @@ #define LED_COLOR_ID_VIOLET5 #define LED_COLOR_ID_YELLOW6 #define LED_COLOR_ID_IR7 -#define LED_COLOR_ID_MAX 8 +#define LED_COLOR_ID_MULTI 8 +#define LED_COLOR_ID_MAX 9 /* Standard LED functions */ /* Keyboard LEDs, usually it would be input4::capslock etc. */ -- 2.25.1
[PATCH v24 03/16] dt: bindings: lp50xx: Introduce the lp50xx family of RGB drivers
Introduce the bindings for the Texas Instruments LP5036, LP5030, LP5024, LP5018, LP5012 and LP5009 RGB LED device driver. The LP5036/30/24/18/12/9 can control RGB LEDs individually or as part of a control bank group. These devices have the ability to adjust the mixing control for the RGB LEDs to obtain different colors independent of the overall brightness of the LED grouping. Datasheet: http://www.ti.com/lit/ds/symlink/lp5012.pdf http://www.ti.com/lit/ds/symlink/lp5024.pdf http://www.ti.com/lit/ds/symlink/lp5036.pdf Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- .../devicetree/bindings/leds/leds-lp50xx.yaml | 179 ++ 1 file changed, 179 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-lp50xx.yaml diff --git a/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml b/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml new file mode 100644 index ..37fadc201097 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml @@ -0,0 +1,179 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/leds-lp50xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LED driver for LP50XX RGB LED from Texas Instruments. + +maintainers: + - Dan Murphy + +description: | + The LP50XX is multi-channel, I2C RGB LED Drivers that can group RGB LEDs into + a LED group or control them individually. + + The difference in these RGB LED drivers is the number of supported RGB + modules. + + For more product information please see the link below: + http://www.ti.com/lit/ds/symlink/lp5012.pdf + http://www.ti.com/lit/ds/symlink/lp5024.pdf + http://www.ti.com/lit/ds/symlink/lp5036.pdf + +properties: + compatible: + oneOf: + - const: ti,lp5009 + - const: ti,lp5012 + - const: ti,lp5018 + - const: ti,lp5024 + - const: ti,lp5030 + - const: ti,lp5036 + + reg: +maxItems: 1 +description: + I2C slave address + lp5009/12 - 0x14, 0x15, 0x16, 0x17 + lp5018/24 - 0x28, 0x29, 0x2a, 0x2b + lp5030/36 - 0x30, 0x31, 0x32, 0x33 + + enable-gpios: +description: GPIO pin to enable/disable the device. + + vled-supply: +description: LED supply. + + child-node: +type: object +properties: + reg: +description: This is the LED module number. + + color: +description: Must be LED_COLOR_ID_MULTI + + function: +description: see Documentation/devicetree/bindings/leds/common.txt + + ti,led-bank: +description: + This property denotes the LED module numbers that will be controlled as + a single RGB cluster. Each LED module number will be controlled by a + single LED class instance. + There can only be one instance of the ti,led-bank + property for each device node. This is a required node is the LED + modules are to be backed. +$ref: /schemas/types.yaml#definitions/uint32-array + +required: + - reg + - color + - function + + grandchild-node: +type: object +properties: + reg: +description: + A single entry denoting the LED output that controls the monochrome LED. + + color: +description: + see Documentation/devicetree/bindings/leds/common.txt + + led-sources: +description: + see Documentation/devicetree/bindings/leds/common.txt + The LED outputs associated with the LED modules are defined in Table 1 + of the corresponding data sheets. + LP5009 - 3 Total RGB cluster LED outputs 0-2 + LP5012 - 4 Total RGB cluster LED outputs 0-3 + LP5018 - 6 Total RGB cluster LED outputs 0-5 + LP5024 - 8 Total RGB cluster LED outputs 0-7 + LP5030 - 10 Total RGB cluster LED outputs 0-9 + LP5036 - 12 Total RGB cluster LED outputs 0-11 + + label: +description: | + Optional node - see Documentation/devicetree/bindings/leds/common.txt + + linux,default-trigger: +description: | + Optional node - see Documentation/devicetree/bindings/leds/common.txt + +required: + - reg + - color + +required: + - compatible + - reg + +examples: + - | +#include +#include +i2c { +#address-cells = <1>; +#size-cells = <0>; + +led-controller@14 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,lp5009"; + reg = <0x14>; + enable-gpios = <&gpio1 16>; + multi-led@1 { +#address-cells = <1>; +#size-cells = <0>; +reg = <1>; +color = ; +function = LED_FUNCTION_CHARGING; + +led@0 { + reg = <0>; + color = ; +}; + +led@1 { + reg = <1>; + color = ; +}; + +led@2 { +
[PATCH v24 04/16] leds: lp50xx: Add the LP50XX family of the RGB LED driver
Introduce the LP5036/30/24/18/12/9 RGB LED driver. The difference in these parts are the number of LED outputs where the: LP5036 can control 36 LEDs LP5030 can control 30 LEDs LP5024 can control 24 LEDs LP5018 can control 18 LEDs LP5012 can control 12 LEDs LP5009 can control 9 LEDs The device has the ability to group LED output into control banks so that multiple LED banks can be controlled with the same mixing and brightness. Inversely the LEDs can also be controlled independently. Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- drivers/leds/Kconfig | 11 + drivers/leds/Makefile | 1 + drivers/leds/leds-lp50xx.c | 777 + 3 files changed, 789 insertions(+) create mode 100644 drivers/leds/leds-lp50xx.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 5b43f4957b8a..fd6e24bb2857 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -375,6 +375,17 @@ config LEDS_LP3952 To compile this driver as a module, choose M here: the module will be called leds-lp3952. +config LEDS_LP50XX + tristate "LED Support for TI LP5036/30/24/18/12/9 LED driver chip" + depends on LEDS_CLASS && REGMAP_I2C + depends on LEDS_CLASS_MULTI_COLOR + help + If you say yes here you get support for the Texas Instruments + LP5036, LP5030, LP5024, LP5018, LP5012 and LP5009 LED driver. + + To compile this driver as a module, choose M here: the + module will be called leds-lp50xx. + config LEDS_LP55XX_COMMON tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501" depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 53bf92f30258..5ac6ed3ed075 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_LEDS_LM3697) += leds-lm3697.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o +obj-$(CONFIG_LEDS_LP50XX) += leds-lp50xx.o obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o obj-$(CONFIG_LEDS_LP5562) += leds-lp5562.o diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c new file mode 100644 index ..3204142c3db7 --- /dev/null +++ b/drivers/leds/leds-lp50xx.c @@ -0,0 +1,777 @@ +// SPDX-License-Identifier: GPL-2.0 +// TI LP50XX LED chip family driver +// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "leds.h" + +#define LP50XX_DEV_CFG00x00 +#define LP50XX_DEV_CFG10x01 +#define LP50XX_LED_CFG00x02 + +/* LP5009 and LP5012 registers */ +#define LP5012_BNK_BRT 0x03 +#define LP5012_BNKA_CLR0x04 +#define LP5012_BNKB_CLR0x05 +#define LP5012_BNKC_CLR0x06 +#define LP5012_LED0_BRT0x07 +#define LP5012_LED1_BRT0x08 +#define LP5012_LED2_BRT0x09 +#define LP5012_LED3_BRT0x0a +#define LP5012_OUT0_CLR0x0b +#define LP5012_OUT1_CLR0x0c +#define LP5012_OUT2_CLR0x0d +#define LP5012_OUT3_CLR0x0e +#define LP5012_OUT4_CLR0x0f +#define LP5012_OUT5_CLR0x10 +#define LP5012_OUT6_CLR0x11 +#define LP5012_OUT7_CLR0x12 +#define LP5012_OUT8_CLR0x13 +#define LP5012_OUT9_CLR0x14 +#define LP5012_OUT10_CLR 0x15 +#define LP5012_OUT11_CLR 0x16 +#define LP5012_RESET 0x17 + +/* LP5018 and LP5024 registers */ +#define LP5024_BNK_BRT 0x03 +#define LP5024_BNKA_CLR0x04 +#define LP5024_BNKB_CLR0x05 +#define LP5024_BNKC_CLR0x06 +#define LP5024_LED0_BRT0x07 +#define LP5024_LED1_BRT0x08 +#define LP5024_LED2_BRT0x09 +#define LP5024_LED3_BRT0x0a +#define LP5024_LED4_BRT0x0b +#define LP5024_LED5_BRT0x0c +#define LP5024_LED6_BRT0x0d +#define LP5024_LED7_BRT0x0e + +#define LP5024_OUT0_CLR0x0f +#define LP5024_OUT1_CLR0x10 +#define LP5024_OUT2_CLR0x11 +#define LP5024_OUT3_CLR0x12 +#define LP5024_OUT4_CLR0x13 +#define LP5024_OUT5_CLR0x14 +#define LP5024_OUT6_CLR0x15 +#define LP5024_OUT7_CLR0x16 +#define LP5024_OUT8_CLR0x17 +#define LP5024_OUT9_CLR0x18 +#define LP5024_OUT10_CLR 0x19 +#define
[PATCH v24 15/16] leds: lp5523: Fix checkpatch issues in the code
Fix checkpatch errors and warnings for the LP5523.c device driver. Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- drivers/leds/leds-lp5523.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 9776dc72a764..f55d97258d5e 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -23,13 +23,13 @@ #define LP5523_PROGRAM_LENGTH 32 /* bytes */ /* Memory is used like this: - 0x00 engine 1 program - 0x10 engine 2 program - 0x20 engine 3 program - 0x30 engine 1 muxing info - 0x40 engine 2 muxing info - 0x50 engine 3 muxing info -*/ + * 0x00 engine 1 program + * 0x10 engine 2 program + * 0x20 engine 3 program + * 0x30 engine 1 muxing info + * 0x40 engine 2 muxing info + * 0x50 engine 3 muxing info + */ #define LP5523_MAX_LEDS9 /* Registers */ @@ -326,7 +326,7 @@ static int lp5523_update_program_memory(struct lp55xx_chip *chip, const u8 *data, size_t size) { u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; - unsigned cmd; + unsigned int cmd; char c[3]; int nrchars; int ret; @@ -468,6 +468,7 @@ static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len) static void lp5523_mux_to_array(u16 led_mux, char *array) { int i, pos = 0; + for (i = 0; i < LP5523_MAX_LEDS; i++) pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i)); @@ -506,7 +507,7 @@ static int lp5523_load_mux(struct lp55xx_chip *chip, u16 mux, int nr) if (ret) return ret; - ret = lp55xx_write(chip, LP5523_REG_PROG_MEM , (u8)(mux >> 8)); + ret = lp55xx_write(chip, LP5523_REG_PROG_MEM, (u8)(mux >> 8)); if (ret) return ret; -- 2.25.1
[PATCH v24 00/16] Multicolor Framework v24
Hello This is the multi color LED framework. This framework presents clustered colored LEDs into an array and allows the user space to adjust the brightness of the cluster using a single file write. The individual colored LEDs intensities are controlled via a single file that is an array of LEDs Dan Dan Murphy (16): dt: bindings: Add multicolor class dt bindings documention leds: multicolor: Introduce a multicolor class definition dt: bindings: lp50xx: Introduce the lp50xx family of RGB drivers leds: lp50xx: Add the LP50XX family of the RGB LED driver dt: bindings: lp55xx: Be consistent in the document with LED acronym dt: bindings: lp55xx: Update binding for Multicolor Framework ARM: dts: n900: Add reg property to the LP5523 channel node ARM: dts: imx6dl-yapp4: Add reg property to the lp5562 channel node ARM: dts: ste-href: Add reg property to the LP5521 channel nodes leds: lp55xx: Convert LED class registration to devm_* leds: lp55xx: Add multicolor framework support to lp55xx leds: lp5523: Update the lp5523 code to add multicolor brightness function leds: lp5521: Add multicolor framework multicolor brightness support leds: lp55xx: Fix checkpatch file permissions issues leds: lp5523: Fix checkpatch issues in the code dt: bindings: Update lp55xx binding to recommended LED naming .../ABI/testing/sysfs-class-led-multicolor| 34 + .../bindings/leds/leds-class-multicolor.yaml | 71 ++ .../devicetree/bindings/leds/leds-lp50xx.yaml | 179 .../devicetree/bindings/leds/leds-lp55xx.txt | 163 +++- Documentation/leds/index.rst | 1 + Documentation/leds/leds-class-multicolor.rst | 86 ++ MAINTAINERS | 8 + arch/arm/boot/dts/imx6dl-yapp4-common.dtsi| 14 +- arch/arm/boot/dts/omap3-n900.dts | 29 +- arch/arm/boot/dts/ste-href.dtsi | 22 +- drivers/leds/Kconfig | 23 + drivers/leds/Makefile | 2 + drivers/leds/led-class-multicolor.c | 210 + drivers/leds/led-core.c | 1 + drivers/leds/leds-lp50xx.c| 777 ++ drivers/leds/leds-lp5521.c| 43 +- drivers/leds/leds-lp5523.c| 62 +- drivers/leds/leds-lp5562.c| 22 +- drivers/leds/leds-lp55xx-common.c | 213 +++-- drivers/leds/leds-lp55xx-common.h | 16 +- drivers/leds/leds-lp8501.c| 23 +- include/dt-bindings/leds/common.h | 3 +- include/linux/led-class-multicolor.h | 121 +++ include/linux/platform_data/leds-lp55xx.h | 8 + 24 files changed, 1972 insertions(+), 159 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-led-multicolor create mode 100644 Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml create mode 100644 Documentation/devicetree/bindings/leds/leds-lp50xx.yaml create mode 100644 Documentation/leds/leds-class-multicolor.rst create mode 100644 drivers/leds/led-class-multicolor.c create mode 100644 drivers/leds/leds-lp50xx.c create mode 100644 include/linux/led-class-multicolor.h -- 2.25.1
[PATCH v24 10/16] leds: lp55xx: Convert LED class registration to devm_*
Convert the LED class registration calls to the LED devm_* registration calls. Acked-by: Jacek Anaszewski Acked-by: Pavel Machek Signed-off-by: Dan Murphy --- drivers/leds/leds-lp5521.c| 9 +++-- drivers/leds/leds-lp5523.c| 9 +++-- drivers/leds/leds-lp5562.c| 9 +++-- drivers/leds/leds-lp55xx-common.c | 15 +-- drivers/leds/leds-lp55xx-common.h | 2 -- drivers/leds/leds-lp8501.c| 9 +++-- 6 files changed, 13 insertions(+), 40 deletions(-) diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 6f0272249dc8..6d2163c0f625 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -541,19 +541,17 @@ static int lp5521_probe(struct i2c_client *client, ret = lp55xx_register_leds(led, chip); if (ret) - goto err_register_leds; + goto err_out; ret = lp55xx_register_sysfs(chip); if (ret) { dev_err(&client->dev, "registering sysfs failed\n"); - goto err_register_sysfs; + goto err_out; } return 0; -err_register_sysfs: - lp55xx_unregister_leds(led, chip); -err_register_leds: +err_out: lp55xx_deinit_device(chip); err_init: return ret; @@ -566,7 +564,6 @@ static int lp5521_remove(struct i2c_client *client) lp5521_stop_all_engines(chip); lp55xx_unregister_sysfs(chip); - lp55xx_unregister_leds(led, chip); lp55xx_deinit_device(chip); return 0; diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index d0b931a136b9..15e7051392f5 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -908,19 +908,17 @@ static int lp5523_probe(struct i2c_client *client, ret = lp55xx_register_leds(led, chip); if (ret) - goto err_register_leds; + goto err_out; ret = lp55xx_register_sysfs(chip); if (ret) { dev_err(&client->dev, "registering sysfs failed\n"); - goto err_register_sysfs; + goto err_out; } return 0; -err_register_sysfs: - lp55xx_unregister_leds(led, chip); -err_register_leds: +err_out: lp55xx_deinit_device(chip); err_init: return ret; @@ -933,7 +931,6 @@ static int lp5523_remove(struct i2c_client *client) lp5523_stop_all_engines(chip); lp55xx_unregister_sysfs(chip); - lp55xx_unregister_leds(led, chip); lp55xx_deinit_device(chip); return 0; diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index edb57c42e8b1..1c94422408b0 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -554,19 +554,17 @@ static int lp5562_probe(struct i2c_client *client, ret = lp55xx_register_leds(led, chip); if (ret) - goto err_register_leds; + goto err_out; ret = lp55xx_register_sysfs(chip); if (ret) { dev_err(&client->dev, "registering sysfs failed\n"); - goto err_register_sysfs; + goto err_out; } return 0; -err_register_sysfs: - lp55xx_unregister_leds(led, chip); -err_register_leds: +err_out: lp55xx_deinit_device(chip); err_init: return ret; @@ -580,7 +578,6 @@ static int lp5562_remove(struct i2c_client *client) lp5562_stop_engine(chip); lp55xx_unregister_sysfs(chip); - lp55xx_unregister_leds(led, chip); lp55xx_deinit_device(chip); return 0; diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index 44ced02b49f9..882ef39e4965 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -181,7 +181,7 @@ static int lp55xx_init_led(struct lp55xx_led *led, led->cdev.name = name; } - ret = led_classdev_register(dev, &led->cdev); + ret = devm_led_classdev_register(dev, &led->cdev); if (ret) { dev_err(dev, "led register err: %d\n", ret); return ret; @@ -490,23 +490,10 @@ int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip) return 0; err_init_led: - lp55xx_unregister_leds(led, chip); return ret; } EXPORT_SYMBOL_GPL(lp55xx_register_leds); -void lp55xx_unregister_leds(struct lp55xx_led *led, struct lp55xx_chip *chip) -{ - int i; - struct lp55xx_led *each; - - for (i = 0; i < chip->num_leds; i++) { - each = led + i; - led_classdev_unregister(&each->cdev); - } -} -EXPORT_SYMBOL_GPL(lp55xx_unregister_leds); - int lp55xx_register_sysfs(struct lp55xx_chip *chip) { struct device *dev = &chip->cl->dev; diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h index 783ed5103ce5..b9b1041e8143 100644 --- a/drivers/leds/leds-lp55xx-common.h +++ b/drivers/
[PATCH v24 05/16] dt: bindings: lp55xx: Be consistent in the document with LED acronym
Update the document to be consistent in case when using "LED". This acronym should be capital throughout the document. Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- Documentation/devicetree/bindings/leds/leds-lp55xx.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt index 1b66a413fb9d..bfe2805c5534 100644 --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt @@ -1,4 +1,4 @@ -Binding for TI/National Semiconductor LP55xx Led Drivers +Binding for TI/National Semiconductor LP55xx LED Drivers Required properties: - compatible: one of @@ -12,8 +12,8 @@ Required properties: - clock-mode: Input clock mode, (0: automode, 1: internal, 2: external) Each child has own specific current settings -- led-cur: Current setting at each led channel (mA x10, 0 if led is not connected) -- max-cur: Maximun current at each led channel. +- led-cur: Current setting at each LED channel (mA x10, 0 if LED is not connected) +- max-cur: Maximun current at each LED channel. Optional properties: - enable-gpio: GPIO attached to the chip's enable pin -- 2.25.1
[PATCH v24 02/16] leds: multicolor: Introduce a multicolor class definition
Introduce a multicolor class that groups colored LEDs within a LED node. The multi color class groups monochrome LEDs and allows controlling two aspects of the final combined color: hue and lightness. The former is controlled via the intensity file and the latter is controlled via brightness file. Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- .../ABI/testing/sysfs-class-led-multicolor| 34 +++ Documentation/leds/index.rst | 1 + Documentation/leds/leds-class-multicolor.rst | 86 +++ MAINTAINERS | 8 + drivers/leds/Kconfig | 11 + drivers/leds/Makefile | 1 + drivers/leds/led-class-multicolor.c | 210 ++ include/linux/led-class-multicolor.h | 121 ++ 8 files changed, 472 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-multicolor create mode 100644 Documentation/leds/leds-class-multicolor.rst create mode 100644 drivers/leds/led-class-multicolor.c create mode 100644 include/linux/led-class-multicolor.h diff --git a/Documentation/ABI/testing/sysfs-class-led-multicolor b/Documentation/ABI/testing/sysfs-class-led-multicolor new file mode 100644 index ..7d33a82a4b07 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-led-multicolor @@ -0,0 +1,34 @@ +What: /sys/class/leds//brightness +Date: March 2020 +KernelVersion: 5.8 +Contact: Dan Murphy +Description: read/write + Writing to this file will update all LEDs within the group to a + calculated percentage of what each color LED intensity is set + to. The percentage is calculated for each grouped LED via the + equation below: + + led_brightness = brightness * multi_intensity/max_brightness + + For additional details please refer to + Documentation/leds/leds-class-multicolor.rst. + + The value of the color is from 0 to + /sys/class/leds//max_brightness. + +What: /sys/class/leds//multi_index +Date: March 2020 +KernelVersion: 5.8 +Contact: Dan Murphy +Description: read + The multi_index array, when read, will output the LED colors + by name as they are indexed in the multi_intensity file. + +What: /sys/class/leds//multi_intensity +Date: March 2020 +KernelVersion: 5.8 +Contact: Dan Murphy +Description: read/write + Intensity level for the LED color within the array. + The intensities for each color must be entered based on the + multi_index array. diff --git a/Documentation/leds/index.rst b/Documentation/leds/index.rst index 060f4e485897..bc70c6aa7138 100644 --- a/Documentation/leds/index.rst +++ b/Documentation/leds/index.rst @@ -9,6 +9,7 @@ LEDs leds-class leds-class-flash + leds-class-multicolor ledtrig-oneshot ledtrig-transient ledtrig-usbport diff --git a/Documentation/leds/leds-class-multicolor.rst b/Documentation/leds/leds-class-multicolor.rst new file mode 100644 index ..8cfbe2e44021 --- /dev/null +++ b/Documentation/leds/leds-class-multicolor.rst @@ -0,0 +1,86 @@ + +MultiColor LED handling under Linux + + +Description +=== +The multicolor class groups monochrome LEDs and allows controlling two +aspects of the final combined color: hue and lightness. The former is +controlled via the multi_intensity array file and the latter is controlled +via brightness file. + +Multicolor Class Control + +The multicolor class presents files that groups the colors as indexes in an +array. These files are children under the LED parent node created by the +led_class framework. The led_class framework is documented in led-class.rst +within this documentation directory. + +Each colored LED will be indexed under the multi_* files. The order of the +colors will be arbitrary. The multi_index file can be read to determine the +color name to indexed value. + +The multi_index file is an array that contains the string list of the colors as +they are defined in each multi_* array file. + +The multi_intensity is an array that can be read or written to for the +individual color intensities. All elements within this array must be written in +order for the color LED intensities to be updated. + +Directory Layout Example + +root:/sys/class/leds/multicolor:status# ls -lR +-rw-r--r--1 root root 4096 Oct 19 16:16 brightness +-r--r--r--1 root root 4096 Oct 19 16:16 max_brightness +-r--r--r--1 root root 4096 Oct 19 16:16 multi_index +-rw-r--r--1 root root 4096 Oct 19 16:16 multi_intensity + +Multicolor Class Brightness Control +=== +The mul
[PATCH v24 07/16] ARM: dts: n900: Add reg property to the LP5523 channel node
Add the reg property to each channel node. This update is to accomodate the multicolor framework. In addition to the accomodation this allows the LEDs to be placed on any channel and allow designs to skip channels as opposed to requiring sequential order. Signed-off-by: Dan Murphy Acked-by: Tony Lindgren CC: Tony Lindgren CC: "Benoît Cousson" Acked-by: Pavel Machek --- arch/arm/boot/dts/omap3-n900.dts | 29 - 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index 4089d97405c9..ebe93b06b4f7 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -618,63 +618,74 @@ indicator { }; lp5523: lp5523@32 { + #address-cells = <1>; + #size-cells = <0>; compatible = "national,lp5523"; reg = <0x32>; clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */ enable-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */ - chan0 { + chan@0 { chan-name = "lp5523:kb1"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <0>; }; - chan1 { + chan@1 { chan-name = "lp5523:kb2"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <1>; }; - chan2 { + chan@2 { chan-name = "lp5523:kb3"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <2>; }; - chan3 { + chan@3 { chan-name = "lp5523:kb4"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <3>; }; - chan4 { + chan@4 { chan-name = "lp5523:b"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <4>; }; - chan5 { + chan@5 { chan-name = "lp5523:g"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <5>; }; - chan6 { + chan@6 { chan-name = "lp5523:r"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <6>; }; - chan7 { + chan@7 { chan-name = "lp5523:kb5"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <7>; }; - chan8 { + chan@8 { chan-name = "lp5523:kb6"; led-cur = /bits/ 8 <50>; max-cur = /bits/ 8 <100>; + reg = <8>; }; }; -- 2.25.1
[PATCH v24 11/16] leds: lp55xx: Add multicolor framework support to lp55xx
Add multicolor framework support for the lp55xx family. Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- drivers/leds/Kconfig | 1 + drivers/leds/leds-lp5521.c| 14 +- drivers/leds/leds-lp5523.c| 14 +- drivers/leds/leds-lp5562.c| 13 +- drivers/leds/leds-lp55xx-common.c | 178 +++--- drivers/leds/leds-lp55xx-common.h | 14 +- drivers/leds/leds-lp8501.c| 14 +- include/linux/platform_data/leds-lp55xx.h | 8 + 8 files changed, 209 insertions(+), 47 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index fd6e24bb2857..501397ab4280 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -389,6 +389,7 @@ config LEDS_LP50XX config LEDS_LP55XX_COMMON tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501" depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501 + depends on OF select FW_LOADER select FW_LOADER_USER_HELPER help diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 6d2163c0f625..6ff81d6be789 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -505,9 +505,16 @@ static int lp5521_probe(struct i2c_client *client, struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); struct device_node *np = client->dev.of_node; + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->cfg = &lp5521_cfg; + if (!pdata) { if (np) { - pdata = lp55xx_of_populate_pdata(&client->dev, np); + pdata = lp55xx_of_populate_pdata(&client->dev, np, +chip); if (IS_ERR(pdata)) return PTR_ERR(pdata); } else { @@ -516,10 +523,6 @@ static int lp5521_probe(struct i2c_client *client, } } - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - led = devm_kcalloc(&client->dev, pdata->num_channels, sizeof(*led), GFP_KERNEL); if (!led) @@ -527,7 +530,6 @@ static int lp5521_probe(struct i2c_client *client, chip->cl = client; chip->pdata = pdata; - chip->cfg = &lp5521_cfg; mutex_init(&chip->lock); diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 15e7051392f5..b076c16df9ab 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -872,9 +872,16 @@ static int lp5523_probe(struct i2c_client *client, struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); struct device_node *np = client->dev.of_node; + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->cfg = &lp5523_cfg; + if (!pdata) { if (np) { - pdata = lp55xx_of_populate_pdata(&client->dev, np); + pdata = lp55xx_of_populate_pdata(&client->dev, np, +chip); if (IS_ERR(pdata)) return PTR_ERR(pdata); } else { @@ -883,10 +890,6 @@ static int lp5523_probe(struct i2c_client *client, } } - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - led = devm_kcalloc(&client->dev, pdata->num_channels, sizeof(*led), GFP_KERNEL); if (!led) @@ -894,7 +897,6 @@ static int lp5523_probe(struct i2c_client *client, chip->cl = client; chip->pdata = pdata; - chip->cfg = &lp5523_cfg; mutex_init(&chip->lock); diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index 1c94422408b0..7ecdd199d7ef 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -520,9 +520,16 @@ static int lp5562_probe(struct i2c_client *client, struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); struct device_node *np = client->dev.of_node; + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->cfg = &lp5562_cfg; + if (!pdata) { if (np) { - pdata = lp55xx_of_populate_pdata(&client->dev, np); + pdata = lp55xx_of_populate_pdata(&client->dev, np, +chip); if (IS_ERR(pdata)) return PTR_ERR(pdata); } else { @@ -531,9 +538,6 @@ st
[PATCH v24 13/16] leds: lp5521: Add multicolor framework multicolor brightness support
Add the multicolor brightness call back to support the multicolor framework. This function allows setting the brightness across grouped LED channels in a single call. Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- drivers/leds/leds-lp5521.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 6ff81d6be789..ef8c3bfa8f3c 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -349,6 +349,25 @@ static int lp5521_run_selftest(struct lp55xx_chip *chip, char *buf) return 0; } +static int lp5521_multicolor_brightness(struct lp55xx_led *led) +{ + struct lp55xx_chip *chip = led->chip; + int ret; + int i; + + mutex_lock(&chip->lock); + for (i = 0; i < led->mc_cdev.num_colors; i++) { + ret = lp55xx_write(chip, + LP5521_REG_LED_PWM_BASE + + led->mc_cdev.subled_info[i].channel, + led->mc_cdev.subled_info[i].brightness); + if (ret) + break; + } + mutex_unlock(&chip->lock); + return ret; +} + static int lp5521_led_brightness(struct lp55xx_led *led) { struct lp55xx_chip *chip = led->chip; @@ -490,6 +509,7 @@ static struct lp55xx_device_config lp5521_cfg = { .max_channel = LP5521_MAX_LEDS, .post_init_device = lp5521_post_init_device, .brightness_fn = lp5521_led_brightness, + .multicolor_brightness_fn = lp5521_multicolor_brightness, .set_led_current= lp5521_set_led_current, .firmware_cb= lp5521_firmware_loaded, .run_engine = lp5521_run_engine, -- 2.25.1
[PATCH] checkpatch: add support for title acrosses three lines in commit id description
The current GIT_COMMIT_ID will report error when the title in commit id description acrosses three lines, take changelog of commit 87b0f983f66f ("net: mscc: ocelot: fix untagged packet drops when enslaving to vlan aware bridge") as a example. It make senses to support three lines title, because three lines could only have about two lines length title, see above example, but I think we don't need to add support for more than three lines length title, ~225 (75 * 3) shoud be enough for any sensible title. This patch adds support for three lines title in the commit id description, and emit diagnostics info when the title acrosses more than three lines. Signed-off-by: Wang YanQing --- Hi! Joe This is the third patch based on previous two patches. Thanks. scripts/checkpatch.pl | 30 +- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index a1e4113..e9c46d3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2899,15 +2899,27 @@ sub process { $orig_desc = $1; $has_parens_and_dqm = 1; } elsif ($line =~ /\b$prefix\s+[0-9a-f]{5,}\s+\(".+$/i && -defined $rawlines[$linenr] && -$rawlines[$linenr] =~ /^\s*.+"\)/) { - $line =~ /\b$prefix\s+[0-9a-f]{5,}\s+\("(.+)$/i; - $orig_desc = $1; - $rawlines[$linenr] =~ /^\s*(.+)"\)/; - $orig_desc .= " " . $1; - $has_parens_and_dqm = 1; - - if ($prefix eq "Fixes:") { +defined $rawlines[$linenr]) { +if ($rawlines[$linenr] =~ /^\s*.+"\)/) { + $line =~ /\b$prefix\s+[0-9a-f]{5,}\s+\("(.+)$/i; + $orig_desc = $1; + $rawlines[$linenr] =~ /^\s*(.+)"\)/; + $orig_desc .= " " . $1; + $has_parens_and_dqm = 1; +} elsif (defined $rawlines[$linenr + 1] && + $rawlines[$linenr + 1] =~ /^\s*.+"\)/) { + $line =~ /\b$prefix\s+[0-9a-f]{5,}\s+\("(.+)$/i; + $orig_desc = $1; + $rawlines[$linenr] =~ /^\s*(.+)/; + $orig_desc .= " " . $1; + $rawlines[$linenr + 1] =~ /^\s*(.+)"\)/; + $orig_desc .= " " . $1; + $has_parens_and_dqm = 1; +} else { + $diagnostics .= "Missing terminal '\")' at the end of title or the title acrosses more than 3 lines.\n"; +} + + if ($has_parens_and_dqm && $prefix eq "Fixes:") { $acrosslines = 1; $diagnostics .= "The title acrosses lines.\n"; } -- 1.8.5.6.2.g3d8a54e.dirty
[PATCH v24 08/16] ARM: dts: imx6dl-yapp4: Add reg property to the lp5562 channel node
Add the reg property to each channel node. This update is to accomodate the multicolor framework. In addition to the accomodation this allows the LEDs to be placed on any channel and allow designs to skip channels as opposed to requiring sequential order. Acked-by: Pavel Machek Signed-off-by: Dan Murphy CC: Shawn Guo CC: Sascha Hauer CC: Pengutronix Kernel Team CC: Fabio Estevam CC: NXP Linux Team --- arch/arm/boot/dts/imx6dl-yapp4-common.dtsi | 14 ++ 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi index 2b9423d55c37..77aa90640052 100644 --- a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi +++ b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi @@ -258,29 +258,35 @@ leds: led-controller@30 { reg = <0x30>; clock-mode = /bits/ 8 <1>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; - chan0 { + chan@0 { chan-name = "R"; led-cur = /bits/ 8 <0x20>; max-cur = /bits/ 8 <0x60>; + reg = <0>; }; - chan1 { + chan@1 { chan-name = "G"; led-cur = /bits/ 8 <0x20>; max-cur = /bits/ 8 <0x60>; + reg = <1>; }; - chan2 { + chan@2 { chan-name = "B"; led-cur = /bits/ 8 <0x20>; max-cur = /bits/ 8 <0x60>; + reg = <2>; }; - chan3 { + chan@3 { chan-name = "W"; led-cur = /bits/ 8 <0x0>; max-cur = /bits/ 8 <0x0>; + reg = <3>; }; }; -- 2.25.1
[PATCH v24 14/16] leds: lp55xx: Fix checkpatch file permissions issues
Fix the checkpatch warnings for the use of the file permission macros. In converting the file permissions to the DEVICE_ATTR_XX macros the call back function names needed to be updated within the code. This means that the lp55xx_ needed to be dropped in the name to keep in harmony with the ABI documentation. Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- drivers/leds/leds-lp55xx-common.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index 19872d1435b3..82c392afeef7 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -83,7 +83,7 @@ static int lp55xx_post_init_device(struct lp55xx_chip *chip) return cfg->post_init_device(chip); } -static ssize_t lp55xx_show_current(struct device *dev, +static ssize_t led_current_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -92,7 +92,7 @@ static ssize_t lp55xx_show_current(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%d\n", led->led_current); } -static ssize_t lp55xx_store_current(struct device *dev, +static ssize_t led_current_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -116,7 +116,7 @@ static ssize_t lp55xx_store_current(struct device *dev, return len; } -static ssize_t lp55xx_show_max_current(struct device *dev, +static ssize_t max_current_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -125,9 +125,8 @@ static ssize_t lp55xx_show_max_current(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%d\n", led->max_current); } -static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, lp55xx_show_current, - lp55xx_store_current); -static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL); +static DEVICE_ATTR_RW(led_current); +static DEVICE_ATTR_RO(max_current); static struct attribute *lp55xx_led_attrs[] = { &dev_attr_led_current.attr, @@ -272,7 +271,7 @@ static int lp55xx_request_firmware(struct lp55xx_chip *chip) GFP_KERNEL, chip, lp55xx_firmware_loaded); } -static ssize_t lp55xx_show_engine_select(struct device *dev, +static ssize_t select_engine_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -282,7 +281,7 @@ static ssize_t lp55xx_show_engine_select(struct device *dev, return sprintf(buf, "%d\n", chip->engine_idx); } -static ssize_t lp55xx_store_engine_select(struct device *dev, +static ssize_t select_engine_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -324,7 +323,7 @@ static inline void lp55xx_run_engine(struct lp55xx_chip *chip, bool start) chip->cfg->run_engine(chip, start); } -static ssize_t lp55xx_store_engine_run(struct device *dev, +static ssize_t run_engine_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -349,9 +348,8 @@ static ssize_t lp55xx_store_engine_run(struct device *dev, return len; } -static DEVICE_ATTR(select_engine, S_IRUGO | S_IWUSR, - lp55xx_show_engine_select, lp55xx_store_engine_select); -static DEVICE_ATTR(run_engine, S_IWUSR, NULL, lp55xx_store_engine_run); +static DEVICE_ATTR_RW(select_engine); +static DEVICE_ATTR_WO(run_engine); static struct attribute *lp55xx_engine_attributes[] = { &dev_attr_select_engine.attr, -- 2.25.1
[PATCH v5] checkpatch: add support to check 'Fixes:' tag format
According to submitting-patches.rst, 'Fixes:' tag has a little stricter condition about the one line summary than normal git commit description: “... Do not split the tag across multiple lines, tags are exempt from the "wrap at 75 columns" rule in order to simplify parsing scripts ...” And there is no sanity check for 'Fixes:' tag format in checkpatch the same as GIT_COMMIT_ID for git commit description, so let's expand the GIT_COMMIT_ID to add 'Fixes:' tag format check support. The check supports below formats: Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") Fixes: 85f7cd3a2aad ("Revert "media: Kconfig: better support hybrid TV devices"") Fixes: 878520ac45f9 ("ext4: save the error code which triggered...") Fixes: 878520ac45f9 ("ext4: save the error code which triggered") Fixes: 277f27e2f277 ("SUNRPC/cache: Allow garbage collection ... ") The check doesn't support below formats and it will emit diagnostics info for them: Fixes: f2c2e717642c ("usb: gadget: add raw-gadget interface" Fixes: 6c73698904aa pinctrl: qcom: Introduce readl/writel accessors Fixes: 3fd6e7d9a146 (ASoC: tas571x: New driver for TI TAS571x power amplifiers) Fixes: 55697cbb44e4 ("arm64: dts: renesas: r8a779{65,80,90}: Add IPMMU devices nodes) Fixes: ba35f8588f47 (“ipvlan: Defer multicast / broadcast processing to a work-queue”) Fixes: cd758a9b57ee "KVM: PPC: Book3S HV: Use __gfn_to_pfn_memslot in HPT page fault handler" Fixes: 9b1640686470 ("scsi: lpfc: Fix use-after-free mailbox cmd completion") Fixes: 03f6fc6de919 ('ASoC: rt5682: Add the soundwire support') Fixes: 03404e8ae652("IB/mlx5: Add support to dropless RQ") Because after GIT_COMMIT_ID supports 'Fixes:' tag format check, it could do the same check as the UNKNOWN_COMMIT_ID, so we don't need UNKNOWN_COMMIT_ID anymore and I decide to delete it. Note: this patch also fixes double quotation mark issue for normal git commit description, and now it supports double quotation mark in title line, for example: Commit e33e2241e272 ("Revert "cfg80211: Use 5MHz bandwidth by default when checking usable channels"") Note: this patch also adds diagnostics info support for normal git commit description format check. Based on original patch by Joe Perches Link: https://lore.kernel.org/lkml/40bfc40958fca6e2cc9b86101153aa0715fac4f7.ca...@perches.com/ Signed-off-by: Wang YanQing --- Hi! Joe and all. This is the v5 version, and I have tested it with below command: $ git log -1 --no-merges --grep="Fixes:" --format=%H | \ while read commit ; do \ ./scripts/checkpatch.pl --git $commit --types=GIT_COMMIT_ID --quiet --nosummary; \ done The result looks good enough already. Thanks. v5: 1: Rebased on '[PATCH v2] checkpatch: fix can't check for too long invalid commit id'. 2: Fix wrong diagnostics info for below non-standard 'Fixes:' formats. a: Fixes: 03404e8ae652("IB/mlx5: Add support to dropless RQ") b: Fixes: da97e18458fb: ("perf_event: Add support for LSM and SELinux checks") 3: Reword the diagnostics info for non-standard title format. v4: 1: Add diagnostics info support, suggested by Joe Perches and Markus Elfring. 2: Delete UNKNOWN_COMMIT_ID and do the check in GIT_COMMIT_ID. v3: 1: Fix a bug in short title line support. v2: 1: Add support for double quotation mark in title line, suggested by Markus Elfring. 2: Add support for short title line with/without ellipsis. 3: Add supported format examples and unsupported format examples in changelog. 4: Fix a little wording issue in changelog , suggested by Markus Elfring. scripts/checkpatch.pl | 120 +- 1 file changed, 90 insertions(+), 30 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9b47584..a1e4113 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2818,51 +2818,101 @@ sub process { $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i && $line !~ /^This reverts commit [0-9a-f]{7,40}/ && ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || +$line =~ /\bfixes:\s+[0-9a-f]{5,}\b/i || ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i && - $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && - $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { + $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i))) { my $init_char = "c"; my $orig_commit = ""; + my $prefix = "commit"; + my $prefix_case = "[Cc]ommit"; my $short = 1; my $long = 0; my $case = 1; my $space = 1; + my $space2 = 1; my $hasdesc = 0; - my $hasparens = 0; +
[PATCH v24 12/16] leds: lp5523: Update the lp5523 code to add multicolor brightness function
Add the multicolor brightness call back to support the multicolor framework. This call back allows setting brightness on grouped channels in a single function. Acked-by: Pavel Machek Acked-by: Jacek Anaszewski Signed-off-by: Dan Murphy --- drivers/leds/leds-lp5523.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index b076c16df9ab..9776dc72a764 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -791,6 +791,25 @@ static ssize_t store_master_fader_leds(struct device *dev, return ret; } +static int lp5523_multicolor_brightness(struct lp55xx_led *led) +{ + struct lp55xx_chip *chip = led->chip; + int ret; + int i; + + mutex_lock(&chip->lock); + for (i = 0; i < led->mc_cdev.num_colors; i++) { + ret = lp55xx_write(chip, + LP5523_REG_LED_PWM_BASE + + led->mc_cdev.subled_info[i].channel, + led->mc_cdev.subled_info[i].brightness); + if (ret) + break; + } + mutex_unlock(&chip->lock); + return ret; +} + static int lp5523_led_brightness(struct lp55xx_led *led) { struct lp55xx_chip *chip = led->chip; @@ -857,6 +876,7 @@ static struct lp55xx_device_config lp5523_cfg = { .max_channel = LP5523_MAX_LEDS, .post_init_device = lp5523_post_init_device, .brightness_fn = lp5523_led_brightness, + .multicolor_brightness_fn = lp5523_multicolor_brightness, .set_led_current= lp5523_set_led_current, .firmware_cb= lp5523_firmware_loaded, .run_engine = lp5523_run_engine, -- 2.25.1
Re: [PATCH v2 2/4] iio: accel: Add driver for wsen-itds accelerometer sensor
On Wed, 29 Apr 2020 15:39:41 +0200 Saravanan Sekar wrote: > Add an iio driver for the wurth elektronic wsen-itds 3-axis accelerometer. > The driver supports the acceleration, temperature data reading and > supports configuring of output data rate, operating mode and scale. > > Signed-off-by: Saravanan Sekar +CC Alex. This one has some unusual buffer handling please, sanity check that it isn't going to cause problem for your core rework. Various comments inline. Note I left the ABI discussion for the documentation patch. Thanks, Jonathan > --- > drivers/iio/accel/Kconfig | 14 + > drivers/iio/accel/Makefile| 1 + > drivers/iio/accel/wsen-itds.c | 947 ++ > 3 files changed, 962 insertions(+) > create mode 100644 drivers/iio/accel/wsen-itds.c > > diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig > index 5d91a6dda894..ad96ba2a9e38 100644 > --- a/drivers/iio/accel/Kconfig > +++ b/drivers/iio/accel/Kconfig > @@ -450,4 +450,18 @@ config STK8BA50 > Choosing M will build the driver as a module. If so, the module > will be called stk8ba50. > > +config WSEN_ITDS > + tristate "Wurth Elektronik WSEN-ITDS 3-Axis Accelerometer Driver" > + depends on I2C > + select IIO_BUFFER > + select IIO_TRIGGERED_BUFFER > + select REGMAP_I2C > + help > + Say yes here to build support for the WSEN-ITDS 3-axis > + accelerometer. > + > + The sensor provides 3-axis Acceleration, Temperature data and > + application specific features like tap, 6D Orinetation, Free-fall > + Motion, Activity etc > + > endmenu > diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile > index 3a051cf37f40..942cab3e1d16 100644 > --- a/drivers/iio/accel/Makefile > +++ b/drivers/iio/accel/Makefile > @@ -61,3 +61,4 @@ st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o > > obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o > obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o > +obj-$(CONFIG_WSEN_ITDS) += wsen-itds.o > diff --git a/drivers/iio/accel/wsen-itds.c b/drivers/iio/accel/wsen-itds.c > new file mode 100644 > index ..d7bc961176c3 > --- /dev/null > +++ b/drivers/iio/accel/wsen-itds.c > @@ -0,0 +1,947 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * WSEN-ITDS 3-axis accel sensor driver > + * > + * Copyright 2020 Linumiz > + * > + * Author: Saravanan Sekar > + * > + * TODO : events - 6D, Orientation, Free-fall, Tap, Motion > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define ITDS_REG_TEMP_L 0x0d > +#define ITDS_REG_DEV_ID 0x0f > +#define ITDS_REG_CTRL1 0x20 > +#define ITDS_REG_CTRL2 0x21 > +#define ITDS_REG_CTRL3 0x22 > +#define ITDS_REG_CTRL4 0x23 > +#define ITDS_REG_CTRL5 0x24 > +#define ITDS_REG_CTRL6 0x25 > +#define ITDS_REG_STATUS 0x27 > +#define ITDS_REG_X_OUT_L0x28 > +#define ITDS_REG_Y_OUT_L0x2a > +#define ITDS_REG_Z_OUT_L0x2c > +#define ITDS_REG_FIFO_CTRL 0x2e > +#define ITDS_REG_FIFO_SAMPLES 0x2f > +#define ITDS_REG_STATUS_DETECT 0x37 > +#define ITDS_REG_WAKEUP_EVENT 0x38 > +#define ITDS_REG_CTRL7 0x3f > + > +#define ITDS_MASK_SCALE GENMASK(5, 4) > +#define ITDS_MASK_BDU_INC_ADD GENMASK(3, 2) > +#define ITDS_MASK_FIFOTHGENMASK(4, 0) > +#define ITDS_MASK_FIFOMODE GENMASK(7, 5) > +#define ITDS_MASK_MODE GENMASK(3, 0) > +#define ITDS_MASK_SAMPLES_COUNT GENMASK(5, 0) > +#define ITDS_MASK_ODR GENMASK(7, 4) > +#define ITDS_MASK_INT_DRDY BIT(0) > +#define ITDS_MASK_INT_FIFOTHBIT(1) > +#define ITDS_MASK_INT_ENBIT(5) > + > +#define ITDS_EVENT_DRDY BIT(0) > +#define ITDS_EVENT_DRDY_T BIT(6) > +#define ITDS_EVENT_FIFO_TH BIT(7) > +#define ITDS_FIFO_MODE_BYPASS0 > +#define ITDS_FIFO_MODE_FIFO BIT(5) > +#define ITDS_DEVICE_ID 0x44 > +#define ITDS_ACCL_FIFO_SIZE 32 > + > +#define ITDS_ACC_CHAN(_axis, _idx) { \ > + .type = IIO_ACCEL, \ > + .modified = 1, \ > + .channel2 = IIO_MOD_##_axis,\ > + .address = ITDS_REG_##_axis##_OUT_L,\ > + .scan_index =
[PATCH v24 06/16] dt: bindings: lp55xx: Update binding for Multicolor Framework
Update the DT binding to include the properties to use the multicolor framework for the devices that use the LP55xx framework. Acked-by: Jacek Anaszewski Reviewed-by: Linus Walleij Signed-off-by: Dan Murphy CC: Tony Lindgren CC: "Benoît Cousson" CC: Linus Walleij CC: Shawn Guo CC: Sascha Hauer CC: Pengutronix Kernel Team CC: Fabio Estevam CC: NXP Linux Team --- .../devicetree/bindings/leds/leds-lp55xx.txt | 149 +++--- 1 file changed, 124 insertions(+), 25 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt index bfe2805c5534..0ccc1efc2499 100644 --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt @@ -1,6 +1,8 @@ Binding for TI/National Semiconductor LP55xx LED Drivers Required properties: +- #address-cells: 1 +- #size-cells: 0 - compatible: one of national,lp5521 national,lp5523 @@ -14,6 +16,18 @@ Required properties: Each child has own specific current settings - led-cur: Current setting at each LED channel (mA x10, 0 if LED is not connected) - max-cur: Maximun current at each LED channel. +- reg: Output channel for the LED. This is zero based channel identifier and + the data sheet is a one based channel identifier. + reg value to output to LED output number + D1 = reg value is 0 + D2 = reg value is 1 + D3 = reg value is 2 + D4 = reg value is 3 + D5 = reg value is 4 + D6 = reg value is 5 + D7 = reg value is 6 + D8 = reg value is 7 + D9 = reg value is 8 Optional properties: - enable-gpio: GPIO attached to the chip's enable pin @@ -35,23 +49,28 @@ example 1) LP5521 on channel 0. lp5521@32 { + #address-cells = <1>; + #size-cells = <0>; compatible = "national,lp5521"; reg = <0x32>; label = "lp5521_pri"; clock-mode = /bits/ 8 <2>; - chan0 { + chan@0 { + reg = <0>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; linux,default-trigger = "heartbeat"; }; - chan1 { + chan@1 { + reg = <1>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; - chan2 { + chan@2 { + reg = <2>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; @@ -70,59 +89,70 @@ ASEL1ASEL0Address VEN VEN 35h lp5523@32 { + #address-cells = <1>; + #size-cells = <0>; compatible = "national,lp5523"; reg = <0x32>; clock-mode = /bits/ 8 <1>; - chan0 { + chan@0 { + reg = <0>; chan-name = "d1"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan1 { + chan@1 { + reg = <1>; chan-name = "d2"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan2 { + chan@2 { + reg = <2>; chan-name = "d3"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan3 { + chan@3 { + reg = <3>; chan-name = "d4"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan4 { + chan@4 { + reg = <4>; chan-name = "d5"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan5 { + chan@5 { + reg = <5>; chan-name = "d6"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan6 { + chan@6 { + reg = <6>; chan-name = "d7"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan7 { + chan@7 { + reg = <7>; chan-name = "d8"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; }; - chan8 { + chan@8 { + reg = <8>; chan-name = "d9"; led-cur = /bits/ 8 <0x14>; max-cur = /bits/ 8 <0x20>; @@ -133,29 +163,35 @@ example 3) LP5562 4 channels are defined. lp5562@30 { + #address-cells = <1>; + #size-cells = <0>; compatible = "ti,lp5562"; reg = <0x30>; clock-mode = /bits/8 <2>; - chan0 { + chan@0 { + reg = <0>; chan-name = "R"; led-cur = /bits/ 8 <0x20>; max-cur = /bits/ 8 <0x60>; }; - chan1 { + chan@1 { + reg = <1>; chan-name = "G";
[PATCH v24 09/16] ARM: dts: ste-href: Add reg property to the LP5521 channel nodes
Add the reg property to each channel node. This update is to accomodate the multicolor framework. In addition to the accomodation this allows the LEDs to be placed on any channel and allow designs to skip channels as opposed to requiring sequential order. Signed-off-by: Dan Murphy CC: Linus Walleij Acked-by: Pavel Machek --- arch/arm/boot/dts/ste-href.dtsi | 22 -- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index 33e3b0b3c53d..ff47cbf6ed3b 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -58,16 +58,21 @@ lp5521@33 { reg = <0x33>; label = "lp5521_pri"; clock-mode = /bits/ 8 <2>; - chan0 { + #address-cells = <1>; + #size-cells = <0>; + chan@0 { + reg = <0>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; linux,default-trigger = "heartbeat"; }; - chan1 { + chan@1 { + reg = <1>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; - chan2 { + chan@2 { + reg = <2>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; @@ -77,15 +82,20 @@ lp5521@34 { reg = <0x34>; label = "lp5521_sec"; clock-mode = /bits/ 8 <2>; - chan0 { + #address-cells = <1>; + #size-cells = <0>; + chan@0 { + reg = <0>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; - chan1 { + chan@1 { + reg = <1>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; - chan2 { + chan@2 { + reg = <2>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; }; -- 2.25.1